Clojure’s great fun, but how can I increase its chances of use at work?
From personal experience and feedback from others, I don’t see big rewrites of systems being a viable way of introducing new technology; who can take the risk of spending 6 months to simply end up with the same business features again? That doesn’t deliver value for the users.
I much more subscribe to the approach of incremental improvement through an approach such as the strangulation pattern. The question was, could I incrementally introduce Clojure?
The server application I work on is for the operations part of the financial Fund of Fund business; financial transactions, valuations and planning. Its a Java application using Spring MVC to expose the API via HTTP.
I was first thinking I needed to use Clojure’s Ring library for the HTTP part which then lead me to the ring-java-servlet project for adding a new Servlet to our existing web.xml.
Upon reflection, this didn’t feel the right way to go. Thinking a bit more, couldn’t I write a Spring MVC controller in Clojure?
The short answer is yes!
Sorry if the colours appear crappy, but somethings changed with code snippets in Octopress and I want to get the article out rather than delay publishing - I will tidy up afterwords!
We use Spring MVC’s annotation-based configuration to find controllers in the application’s classpath. This means we need to use Clojure’s AOT (Ahead Of Time) compilation so that there is a class to find at start-up time.
This was the first time I’ve used Clojure’s support for generating a class, which wasn’t difficult. What was more challanging was getting the annotations correct.
Clojure has support for adding metadata to symbols and collections. This approach is used for adding Java annotations to generated classes and methods. The tricky bit is working out what value to give the annotation (it’s a map so every annotation needs a value).
If there’s no value for the annotation, you can use an empty map. The empty string given to the Controller annotation is because you can give an optional name.
In Java I’d use a single string to add the URL template to the RequestMapping annotation, but if you read the source code for the annotation you’ll notice that it is actually an array. I’m not sure if the ability to add a single string is some syntactic sugar of the Java compiler, but you can’t do this from Clojure; you need to make it a list.
For building, I used Leiningen via Eclipse’s CounterClockWise Clojure plug-in. You need to remember to tell Leiningen to do the AOT build as well otherwise the gen-class declaration is ignored.
Now I just need to find a new part of the system to implement where choosing Clojure would be the smart thing to do…