Sane web development with Compojure, Jetty, and Maven

I find myself slipping back into web development in the new year. I’ve known this was coming for some time, so I’ve had a fair chance to carefully choose my weapons:

What has really tied this all together is Maven (and a couple of plugins for it), which has enabled me to fill in a couple of gaps in what is otherwise the most pleasant web development environment I’ve ever used (where Pylons was the prior champ, FWIW).

The biggest gap is in automatic application reloading/redeployment – in concrete terms, when I save a Clojure source file, my application should be reloaded nearly immediately, thereby avoiding any code-build-deploy cycle. To be precise, this capability is built into Jetty (as it is in many other Java-based app servers). The question is, how to most readily utilize it.

I came across this post by Jim Downing, which describes how to set up a Maven project for a Compojure application, enabling development-mode app reloading using the maven-jetty-plugin (the formatting on that post appears to have degraded since it was published; you can check out the project described in the post here). This certainly appears to fit the bill; unfortunately, the setup that Jim describes there doesn’t quite work for me – when I save a source file, the application is automatically redeployed, but no changes are picked up.

Thankfully, the fix is easy. Below is the relevant section of my pom.xml, configuring maven-jetty-plugin to add my Clojure source root as an extra classpath element. This allows Clojure, running in the jetty application server, to find and load any Clojure source files that are newer than their AOT-compiled counterparts in the usual target/classes directory (note the webAppConfig/extraClasspath elements):

            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">

With that, I’m just a mvn jetty:run away (or, really, a single click away in NetBeans) from having a development process identical to paster serve --reload, with the added benefit of Clojurey goodness.

♬♫The more you know…♪♬

(Apologies to those who aren’t familiar with American pop culture.)

If you want to compile Clojure code (and really, if you’re involved in a project of any size or importance, you should be, if only to avoid forcing Clojure to generate bytecode at runtime, which will slow down the sort of rapid development enabled by automatic app redeployment as describe above), do me a favor and use clojure-maven-plugin. (The post I reference above manually invokes the Clojure compiler using ant’s exec task, but that was what you had to do back in July 2009.) It’s a great piece of kit, and additionally serves as a perfect gateway drug to Maven – which, despite the controversy, and my own quibbles with various aspects of it, will eventually save your bacon in any larger project.

7 thoughts on “Sane web development with Compojure, Jetty, and Maven

    1. You mean, of course, Foundercast. Doug wanted to take a break from it for a while – not sure when (if?) he wants to move it along again.

      In the meantime, you can check out Strictly Professional, which is the podcast that I host (also occasionally).

  1. Very very cool.

    Thanks for clueing me in to Enlive. It’s a great combination with Compojure.

    Just a small detail, your contextPath tag belongs within the webAppConfig tag, otherwise it doesn’t work, i.e. it will ignore you if you change the context path to something else than ‘/’.

    1. We’re using CouchDB almost exclusively at this point, interfacing with it using clutch, which is an excellent couch access lib for clojure (disclosure: which I’ve contributed to here and there).

  2. This post is really not very easy to follow. It’s unclear what needs to be used from Jim Downing’s post and what should be replaced w/ clojure-maven-plugin.

    An updated template pom.xml with your changes and clojure-maven-plugin would be helpful.

    1. Maybe someone can put together an archetype for this sort of thing. Otherwise, if you grok maven, splicing the snippet I provided into your pom is pretty trivial.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s