This post walks through the steps for using Clojure to write an extremely simple web application. The web application will use the Ring and Enlive libraries.

Firstly install Leiningen, this is a simple build tool for Clojure, follow the instructions on the web page and place the lein somewhere on your executable path.

Now use leiningen to create a new clojure project; I always name my projects after vegetables so we will call this one sprout. Execute this command at the command line:

% lein new sprout

This will create a directory called sprout. Change into the newly created directory and issue the following commands:

sprout% lein deps sprout% lein test

The first command will download some dependent libraries and the second command will run a default unit test that should fail like this:

[null] Testing sprout.core-test [null] FAIL in (replace-me) (core_test.clj:6) [null] expected: false [null] actual: false [null] Ran 1 tests containing 1 assertions. [null] 1 failures, 0 errors. [null] -------------------- [null] Total: [null] Ran 1 tests containing 1 assertions. [null] 1 failures, 0 errors.

If this all goes successfully we have a project ready to work with. Working with Clojure is made a lot easier if you have a working REPL to interact with, create a file called clj in the project directory containing a script like this:

#!/bin/bash LIBS=`printf "%s:" lib/*.jar | sed s/:$//` if [ $# -eq 0 ]; then java -cp $LIBS:src clojure.main else java -cp $LIBS:src clojure.main $1 -- $@ fi

Make sure this script is executable and check that it works from the command line like this:

sprout%./clj Clojure 1.1.0 user=> (+ 2 3) 5 user=> ^C sprout%

Now edit the project.clj file to add dependencies for the Ring and Enlive libraries, the file should look like this:

(defproject sprout "1.0.0-SNAPSHOT" :description "Simple program to play with ring and enlive" :dependencies [[org.clojure/clojure "1.1.0"] [org.clojure/clojure-contrib "1.1.0"] [ring "0.1.1-SNAPSHOT"] [enlive "1.0.0-SNAPSHOT"]])

Now use leiningen to download the dependencies:

sprout% lein deps

Now let us create a basic application that will serve some web pages, edit the file src/sprout/core.clj to look like this:

(ns sprout.core) (defn router [req] (condp = (:uri req) "/error" {:status 404 :headers {"Content-Type" "text/html"} :body (str "Error")} "/info" {:status 200 :headers {"Content-Type" "text/html"} :body (str "This is Ring on " (:server-name req)) } {:status 200 :headers {"Content-Type" "text/html"} :body (str "Welcome")})) (defn app [req] (router req))

This contains two functions, the router function generates different pages dependent on the requested uri and the app function that forwards a request to the router. We can test this code with a unit test, edit the file test/sprout/core_test.clj and make it look like this:

(ns sprout.core-test (:use [sprout.core] :reload-all) (:use [clojure.test])) (deftest not-found-error (let [req {:uri "/error"} resp (app req)] (is (= 404 (:status resp))))) (deftest default-page (let [req {:uri "/index.html"} resp (app req)] (is (= 200 (:status resp))))) (deftest info-page (let [req {:uri "/info" :server-name "test"} resp (app req)] (testing "Info page shown" (is (= 200 (:status resp))) (is (= "This is Ring on test" (:body resp))))))

You can run this test with lein test at the command line.

So far this is pure functional Clojure with no real web pages in site, just a map being passed into a function and a different map being returned, the maps happen to be keyed with keys that look a bit like http requests and responses. The Ring library wraps these functions with adapters that talk to real web containers we will use Jetty to demonstrate real web pages.

Create a new file in src/sprout called run.clj and edit it to appear like this:

(ns sprout.run (use [ring.adapter.jetty]) (use [sprout.core])) (run-jetty app {:port 8080})

Now from the command line do this:

sprout%./clj src/sprout/run.clj 2010-02-27 14:08:03.602::INFO: Logging to STDERR via org.mortbay.log.StdErrLog 2010-02-27 14:08:03.604::INFO: jetty-6.1.14 2010-02-27 14:08:03.727::INFO: Started SocketConnector@0.0.0.0:8080

Using a browser visit the urls http://localhost:8080, http://localhost:8080/info and http://localhost:8080/error. All being well you should see a welcome page, an info page and a 404 error.

Ring provides a further level of wrapper functions that enable html processing pipelines to be built using simple functions written in Clojure. The pages you have seen so far haven’t looked very impressive, they are not even valid HTML! We could embed the HTML in the code or write a library to generate HTML in Clojure but instead we will use Enlive.

Enlive is a selector based templating library, this differs from templating languages such as JSP or ASP in that the raw html remains untouched, functions are written that use css selectors to replace and augment the existing html. Create a file in the src/sprout directory called enlive.clj and edit it to appear like this:

(ns sprout.enlive (:use [net.cgrand.enlive-html])) (deftemplate t1 "templates/t1.html" [] [:h1] (content "heading")) (defn enlive-template [] (apply str(t1)))

The deftemplate declaration creates a template called t1, that takes no parameters and substitutes the content of any h1 tags with the word heading. The function enlive-template just applies the template to generate HTML.

Now add a new mapping to the router defined in src/sprout/core.clj to use this function, the file should now look like this:

(ns sprout.core (:use sprout.enlive)) (defn router [req] (condp = (:uri req) "/error" {:status 404 :headers {"Content-Type" "text/html"} :body (str "Error")} "/info" {:status 200 :headers {"Content-Type" "text/html"} :body (str "This is Ring on " (:server-name req)) } "/enlive" {:status 200 :headers {"Content-Type" "text/html"} :body (enlive-template) } {:status 200 :headers {"Content-Type" "text/html"} :body (str "Welcome")})) (defn app [req] (router req))

Running the run script again:

prout%./clj src/sprout/run.clj 2010-02-27 15:10:35.476::INFO: Logging to STDERR via org.mortbay.log.StdErrLog 2010-02-27 15:10:35.479::INFO: jetty-6.1.14 2010-02-27 15:10:35.528::INFO: Started SocketConnector@0.0.0.0:8080

Now go to http://localhost:8080/enlive and an HTML page should be visible.

This has been an extremely basic introduction to using Ring and Enlive with Clojure to serve up web pages. I’ll be expanding on this example at a later date to dive deeper into the functionality of Ring, Enlive and Clojure.