If you read my last Compojure post, you will soon discover (like me) that you need to put in a little bit more work to get a practical setup. Thanks to arbscht in #compojure for showing me all of this.

So first up you need to create a new Leiningen project. Luckily there’s an inbuilt command to help.

lein new example
cd example

Now you should be able to see the skeleton of your new project. Next, you need to set up the project.clj file, it’s used to set the name and dependencies for the project.

You will need to add a description, adjust the version and add the required dependencies for a Compojure based website. Here’s what an example:

(defproject example "0.0.1"
  :description "Test website to learn Compojure"
  :dependencies [[org.clojure/clojure "1.1.0"]
                 [org.clojure/clojure-contrib "1.1.0"]
                 [compojure "0.4.0-SNAPSHOT"]
                 [hiccup "0.2.3"]
                 [ring/ring-jetty-adapter "0.2.0"]
                 [leiningen/lein-swank "1.2.0-SNAPSHOT"]])

Now inside ./src/example/ we need to create a server.clj file that we can use to setup the web server, here’s mine:

(ns example.server
  (:use compojure.core
        ring.adapter.jetty))
(defroutes main-routes
  (GET "/" []
    "<h1>Hello World</h1>")
  (GET "/test/:name" req
       (test-page (:name (:params req))))
  (ANY "*" []
    {:status 404, :body "<h1>Page not found</h1>"}))

(defn start []
  (run-jetty #'main-routes {:port 8080 :join? false}))

(defn test-page [name]
  (str "<b>Hello" name "</b>"))

Three interesting things to note with that example:

  1. We put the run-jetty call inside a function. That way when the file is included the server doesn’t automatically start. Inconvenient but it lets us :reload the file as much as we need.
  2. We pass run-jetty #'main-routes instead of just main-routes, that is so that any changes to our routes are put in effect as soon as the (defroutes main-routes ...) s-exp is re-evaled.
  3. The page /test/* is going to display “Hello *” as an example of how to capture “parameters” from the user. Try just passing req instead of (:name (:params req)) to see what else is available to you.

Now we are ready to give this a go, make sure you’re in the root of your project and type:

lein deps
lein swank

To start a Clojure process for your project that also runs a Swank server. Then you need to open Emacs and do the following:

M-x slime-connect ret ret
(use 'example.server)
(example.server/start)

Now browse to http://localhost:8080, and you should see a “Hello world” page. Browse to http://localhost:8080/test/Dave, and it should say “Hello Dave”. Finally, change your server.clj to say “Hello new world” and re-eval the (defroutes ...). The change should take effect as soon as you refresh your browser!

Cheers, Dave.