Learning to Build Clojure Webapps

A while ago I gave a talk at an internal event at Zenika Singapore. We were free to choose a topic so I chose something I thought I didn't know enough about - what it feels like to build a web app in Clojure. This post is a transcript of the talk. I'll go into some details on Clojure, which libraries you can use to build web apps and how all of that felt to me.

Clojure

Clojure is a LISP dialect that targets the JVM, Microsofts CLR and JavaScript by means of ClojureScript. It is a functional and dynamic language. One of its specialities are the immutable data structures that rely on structural sharing when appending or removing elements. This allows for good performance even though maintaining immutability.

I got mainly interested in Clojure because

Due to some of its features like Software Transactional Memory (STM) and atoms it can be especially well suited for building correct concurrent applications.

One aspect that I deem important as well: It seems to be a quite friendly community and I liked both of the user groups I attended, Clojure Berlin and the Clojure Meetup Singapore.

If you want to get started with Clojure it's best to start with the very common build tool Leinigen. Among other things it offers a simple way to build and run projects, standalone or in the REPL, a feature that is commonly used with LISP dialects.

Using the REPL and Leiningen alone will not be enough for you, you at least need something to edit files. Naturally many people seem to use emacs, besides that there is also Cursive (built on IntelliJ), Lighttable (an experimental IDE) and Nightcode (a very simple editor with built in REPL).

Nightcode

To get started with a project you can just install Leiningen and get started by firing up a REPL using lein repl.

Let's start with a simple operation, adding two numbers.

user=> (+ 2 3)
5

This already shows two of the more unusual features of Clojure. First, all of the code is represented as a list. That is why even the operation is enclosed in brackets. Second, Clojure uses the prefix notation even when it comes to mathematical operations. But this has also the benefit that you can just increase the number of parameters for the add operation.

user=> (+ 2 3 4 5)
14

And if you think about it: That is not that unusual at all. If you see + as the name of a function (which it is) this is very similar to the way you would call a function in a c like language.

plus(2, 3, 4, 5) 

Of course you can also assign the result of a calculation to a variable.

user=> (def result (+ 2 3 4 5))
#'user/result
user=> result
14
user=> (- result 1)
13

Besides numeric values there are also other data types, e.g. strings and boolean values that you can use directly.

It is very easy to create functions as well.

user=> (defn append-mod [val] (str val "-mod"))
#'user/append-mod
user=> (append-mod "some-value")
"some-value-mod"

The more interesting data structures are the collections. There are vectors for sequential data.

user=> (def characters ["a" "b" "c"])
#'user/characters
user=> (characters 0)
"a"
user=> (characters 1)
"b"

And there are maps, often used with so called keywords as keys.

user=> (def my-map {:key "value" :foo "bar"})
#'user/my-map
user=> (my-map :key)
"value"

Being a functional language it is very common to do transformation on collections, e.g. using the map operation. This also shows the use of functions as first class citizens as seen by passing in the upper-case function.

userer=> (map clojure.string/upper-case characters)
("A" "B" "C")

Important: this doesn't modify the existing collection - it creates a new one. All possible due to the efficient implementation of the data structures.

Challenges

It is true that Clojure has a simple syntax that makes it easy to get started. But there are still many things to learn and when beginning it doesn't matter that much if something is syntax, a macro or a library call. It can be especially confusing that sometimes there are related but different concepts. For example those are all different ways to create a function, but for different purposes.

One thing that is still difficult for me is to decide how to structure programs in Clojure. It seems to be common to have a lot of functions in the same namespace. I imagine that it is difficult to decide which function is responsible for which data or task.

Finally, at least to me, the docs can be confusing.

Building Web Apps

As a general purpose language Clojure can of course be and is used a lot for building web apps as well. Compared to the Java landscape there is a lot less choice, a very common combination is to use three libraries, Ring as the core library, Compojure for routing and Hiccup for templating.

Ring is implemented as a pipeline. First there is an adapter that is used to map to an internal request/response representation and that adapts to an existing web runtime. There is an adapter that use Jetty or another one that only relies on the Servlet API which makes it possible to deploy a Ring app to any servlet container.

Ring flow

Next there are the middlewares. Those are like filters in the Java servlet world and can be used to enhance the application. By default there are some middlewares configured e.g. for handling parameters, session or cookies.

In the end a request hits the handler which transforms the request to a response.

Compojure can help you implement the routing for those handlers. This is a simple example that creates one successful route and one function to handle paths that are not found.

(defroutes app
  (GET "/" [] "<h1>Hello World</h1>")
  (route/not-found "<h1>Page not found</h1>"))

If you want to get started yourself the easiest way is to use the leiningen-compojure template that creates the application skeleton for you.

lein new compojure my_project_name

This will create the necessary folder structure, a leiningen file, a handler and a test for it.

If you don't want to write all the html in Strings yourself like in the example above it's time for a templating library. One that is often used in combination with Ring and Compojure is Hiccup. It allows you to write Clojure code that is being translated to HTML.

user=> (html [:span {:class "foo"} "bar"])
"<span class="\"foo\"">bar</span>" 

I developed a very simple application using those libraries: a tool for seeing and adding vocabulary. Once started you can see a list of vocabulary, add more words and look up translations. I wouldn't say it's production ready for now, one reason being that it stores all the data in memory only :) You can find the source code on Github.

The worlds most advanced vocabulary trainer

It contains a GET and a POST route for reading the list and adding a word and a Hiccup template.

Conclusion

It was fun working on a new language and after grasping the basics of Clojure it is easy to get started with a webapp, mainly because of the Leiningen Compojure template that makes it easy to set up a new project. There is a lot of ready made functionality available in the Ring middlewares. Hiccup still feels a bit weird to me, I am not too sure if many frontend developers are keen on working with it.

I wish I would have had more time to prepare the talk and work on the example. There are still a lot of things I have no idea about and I hope I can find some time to continue learning. Even though I don't foresee to use Clojure in a project at work anytime soon it can be very benificial to learn about new approaches - your perception of some language features can change.

If you want to get started with Clojure as well - I can especially recommend Aphyrs series on the basics. I have seen a useful talk by different InnoQ people over the years that especially covers the web libraries. A recording by Michael Vitz is available on YouTube.