comments 25

Web Application Development with Clojure – Part 1

This post is part of the Web Application Development with Clojure tutorial.

Introduction

Clojure is general-purpose compiled, dynamic, Lisp-dialect language that targets JVM (also .Net CLR and JavaScript). There are many ways you can build a Web application using Clojure. You can use a simple framework like Noir or you can pick and choose libraries you like and build your own web stack along the way. I assume that you already started learning Clojure using some tutorial or a good Clojure book.

In this blog post series I’ll explain how to build a web application using Clojure. Creating a blogging engine seems to be the equivalent “hello world” for Web application development, so let us build a blog engine in Clojure: Clog.

Clojure Web Application Toolkit

There are many fantastic libraries available for Clojure for any type of task you can imagine and superior Java Interoperability of Clojure gives you seamless access to innumerable Java libraries and API that you can benefit from. To build a database backed web application you might need some standard libraries to perform HTTP Routing, Database connectivity and migrations, HTML Templates etc.

We’ll use the following libraries to build our web application:

  • Clojure1.3.0 – The language.
  • ring –  1.0.1 – The HTTP Abstraction API and Middleware.
  • moustache  - 1.1.0 – HTTP Routes DSL
  • lobos –  1.0.0-SNAPSHOT – Database Schema Manipulation and Migrations
  • korma0.2.1 – DSL for Database Connectivity and Interaction.
  • enlive1.0.0 – Selector based HTML library.
  • postgresql9.1-901.jdbc4 – PostgreSQL JDBC4 driver.
  • clj-yaml0.3.1 – A snakeyaml wrapper for YAML file parsing and generation.
Apache Maven is more than just a “dependency management” tool. It is a “software project management and comprehension tool”. Don’t worry too much if you don’t comprehend what it means.

The above list is just for your information. You don’t need to individually download those libraries. For those of you who are familiar with Java dependency management tools like Apache Maven or Apache Ivy, Clojure ecosystem has similar build tool called Leineingen which helps you configure your project, manage dependencies etc.

Leiningen is for automating Clojure projects without setting your hair on fire.Working on Clojure projects with tools designed for Java can be an exercise in frustration. With Leiningen, you just write Clojure.

Using Leiningen you can configure your project settings using Clojure. Leiningen uses Apache Maven for dependency resolution. So you can add any library from a maven repository as a dependency to your Clojure project. Installing Leiningen is very straight forward, which is left as an exercise to the reader.

Project Setup

After you have installed leiningen you can create a project by typing the following command in your terminal (or command) window.

lein new clog

If leiningen is installed properly you should see an output of the command similar to the following

→ ~$ lein new clog
Created new project in: /Users/vijaykiran/clog
Look over project.clj and start coding in clog/core.clj

When you run the above command, leiningen will create a simple Clojure project named “clog” for you. If you look into the clog folder, you see there are several files and folders created. Again, if you are familiar with Apache Maven, you can see the structure is pretty similar to standard Maven project. Anyway, let us take a quick look at the generated files and folders:

  • README – A simple README file
  • project.clj – The Clojure project configuration file – written in Clojure.
  • src – Folder for your source code
  • test – Folder for your tests
  • src/clog/core.clj – The “core” Clojure file for your project (You can change it to whatever you want, but for simplicity, we’ll leave it as it is).

Create a directory called resources inside the clog directory. This directory will be used to store and serve the static resources like images, CSS files etc. of our web application.

There are many configuration options available to set up your project via the project.clj file. But for now we’ll just focus on simple things like adding dependencies.

Adding Dependencies

If you open the project.clj file under your clog folder, you can already see that there are a couple of dependencies configured using defproject macro.

(defproject clog "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.3.0"]])

Let us update the file to add the required libraries (as shown above). Use your favorite editor to edit the project.clj, we’ll later setup an IDE for editing our source code. While we are there, we’ll also fix the version and description of the project and set them to 0.0.1-SNAPSHOT and A Clojure Blogging Engine.

This would be good time to create a version control repository and add your source code to it. If you are using git, you can see that lein new has already created a .gitignore file for you. So all you need to do is git init, git add . and git commit -m “Clog project – init” to create and initialize the git repository for your project.
(defproject clog "0.0.1-SNAPSHOT"
  :description "Clog: A Blog engine written in Clojure"
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [ring "1.0.1" ;;; Exclude the clojure, clj-stacktrace from ring dependency
                   :exclusions [org.clojure/clojure
                               clj-stacktrace]]
                 [net.cgrand/moustache "1.1.0"]
                 [lobos "1.0.0-SNAPSHOT"]
                 [korma "0.2.1"]
                 [enlive "1.0.0"]
                 [postgresql "9.1-901.jdbc4"]
                 [clj-yaml "0.3.1"]])

After you edit the project.clj, run the lein deps command to download the required dependencies. You should see output similar to this:

~/clog $ lein deps
...
Copying 32 files to /Users/vijaykiran/clog/lib

That is all you need to do to configure and setup your project. Of course, we still need to set up the database, which we will come back to at a later stage. Next step is configure a development environment a.k.a an IDE.

IDE Configuration

All major IDEs (Eclipse with Couter-ClockWise plugin, IntelliJ IDEA with La Clojure plugin and Netbeans with Enclojure plugin) have Clojure support via Plugins. Many Clojure developers seem to prefer Emacs instead of using IDEs.

Emacs with SLIME

Emacs seems to be the favorite editor of most people in Clojure community. Emacs has several “plugins” that help with editing Clojure files. Learning & using Emacs can be intimidating at first but personally I find it very rewarding experience. If you are an Emacs user you can use clojure-mode, slime, swank and paredit as your development environment. There are several tutorials available on how to configure Emacs for clojure development. I encourage you to check them out if you want to use Emacs as your “IDE”. I use Emacs with lein swank, clojure-mode and slime-connect. I configured emacs with emacs starter kit and other plugins, FWIW, this is how it looks:

You can see project.clj in editor mode, Clojure REPL using slime-connection and lein swank running in Emacs’s eshell on this image. Since my Emacs configuration is based on Live-Coding Emacs setup, I get a nice color scheme and auto-completion.

IntelliJ IDEA

For this tutorial I will use IntelliJ Community Edition with La Clojure and Leiningen Plugins. After downloading the IDE make sure you install and enable the plugins.

After you have installed both plugins, select Open Project .. option in IntelliJ and choose the project.clj from clog folder. Leiningen plugin will detect the project.clj and open the clog project as an IntelliJ project as shown below.

Make sure that you add Clojure facet to the module, which will allow you start the Clojure console for the project. Also, add the clojure 1.3 library for project if you have another version of clojure installed globally. This will make sure that when you start the Clojure console, it will use the correct Clojure version.

Startup code for Jetty Server

First step in developing a web application is to startup the jetty server. We will use the ring-jetty adapter to start-up the Jetty server. Edit the core.clj file and add the following code to it:

When you import other namespaces using :use you are actually importing all the symbols into current namespace. This might create conflicts with the symbols you define in your namespace, so it is advised that you use :require instead. To keep things very simple, we use :use here.
(ns clog.core
  (:use ring.adapter.jetty
        ring.middleware.resource
        ring.util.response
        net.cgrand.moustache))
 
;;; A simple handler to show send some response to the client.
(defn index
  [req]
  (response "Welcome, to Clog - A Blog Engine written in Clojure"))
 
;; Routes definition
(def routes
  (app
    [""] index))
 
;;; start function for starting jetty
(defn start
([] (start 8080)) ; port - default to 8080
([port] (run-jetty #'routes {:port port :join? false})))

Let us take a closer look on the code we added to the core.clj. First we defined the namespace clog.core and imported the namespaces via :use. Then we defined a simple function called index that uses the ring response method to send some text as response.

We used the moustache macro app to define the routes that we want to handle. In our case, we want the route that matches the url segment with parts [""] to the function index, which is another way saying when a client sends a request with no url segments or parameters, let the function index handle it.

Next we defined a function start that will help us to start a jetty server. It takes a port parameter, if it isn’t supplied, the run-jetty function from ring-jetty adapter will start the jetty server on port 8080.

REPL is an acronym for Read Eval Print Loop, which does what the name implies – it reads the code, evaluates it, prints the result and loops back to read step. The main difference between Clojure REPL and other languages’ is during the Eval step, the code is compiled.

Running the program in lein REPL

You can run this program using REPL in command line. Open a terminal window, and change to the clog directory. Then type lein repl, which will start a new Clojure REPL with the class path setup to include our project’s libraries. In the REPL, first import the clog.core namespace by typing use ‘clog.core. Now you can use the start function to start jetty on your port of choice. Here’s the transcript of the commands and their results:

→ ~$ cd clog
→ clog[master]/$ lein repl
REPL started; server listening on localhost port 53791
user=> (use 'clog.core)
nil
user=> (start 8888)
2012-01-11 16:10:41.640:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
#
2012-01-11 16:10:41.642:INFO::jetty-6.1.25
2012-01-11 16:10:41.654:INFO::Started SocketConnector@0.0.0.0:8888
user=>

Open a browser window and open the URL http://localhost:8888. You should see the message Welcome, to Clog – A Blog Engine written in Clojure.

Running the program in IntelliJ IDE

To run this program in IntelliJ, start the Clojure console by clicking on the Tools -> Start Clojure Console. This will start a console in your IDE with the your module’s class path. Now type (use ‘clog.core) and (start 8888) in your clojure console. You should see the output as shown below:

You can now browse to the URL: http://localhost:8888 to see the response.

Conclusion

This concludes the part 1 of this series. In part 2 I’ll show you how to create the database schema and migrations using Clojure and lobos. Make sure you subscribe to the RSS feed or follow me on Twitter to get notified.

If you have any feedback on this article and its content, you can contact me via Twitter.

25 Comments

  1. Pingback: VijayKiran.com – Web Application Development with Clojure – Part 2

  2. Pingback: VijayKiran.com – Web Application Development with Clojure – Part 2

  3. Pingback: VijayKiran.com – Web Application Development with Clojure – Part 3

  4. Pingback: VijayKiran.com – Web Application Development with Clojure – Part 3

  5. Jaydonnell

    Great series! One thing that is always missing in the clojure web app blog posts is the production/server setup. How do you run this on the server?

  6. Dtdave

    Really enjoying your  series. Everything is fine working with the repl. On Intellij I get the following when I start the console:
     Could not locate ring/adapter/jetty__init.class or ring/adapter/jetty.clj on classpath:  (core.clj:1) Any chance you could help?

  7. David Simmons

    Hi Vijay 

    I think (defn [port]…. should be (defn [& port] ….    without the & you have to specify a port number and you don’t need to have the (or port 8080) for a default value.

    Great series by the way

  8. Pingback: Clojure: Links, News And Resources (6) « Angel ”Java” Lopez on Blog

  9. Pingback: VijayKiran.com – Web Application Development with Clojure – Part 1 « that dismal science

  10. pablo12

    Hey,

    with leiningen 2 I get this Exception when trying to run (use ‘cloq.core):

    user=> (use ‘cloq.core)
    IllegalStateException not-found already refers to: #’ring.util.response/not-found in namespace: cloq.core clojure.lang.Namespace.warnOrFailOnReplace (Namespace.java:88)

  11. pablo12

    Hey,

    with leiningen 2 I get this Exception when trying to run (use ‘cloq.core):

    user=> (use ‘cloq.core)
    IllegalStateException not-found already refers to: #’ring.util.response/not-found in namespace: cloq.core clojure.lang.Namespace.warnOrFailOnReplace (Namespace.java:88)

    • “not-found” might be defined already in another namespace – can you post your code on a gist ?

      Alternatively you can change the :use calls to :require and add functions that are used the current namespace – that will be a cleaner approach.

    • Alex Nelson

      I get a similar error, it’s not Leiningen 2′s fault. If you actually use clojure 1.3, and the libraries as specified above, it works.

      However, if you’re trying to be clever (and if you’re cleverness causes errors, like me), then the source is really a newer version of ring and clojure…but not Leiningen. That said, I have no clue how to fix it :’(

      Edit: I think I found the source of the problem, namely, the start function uses (run-jetty #’routes …) and well clojure doesn’t like the hashtag-quote construct for routes, for some reason…

  12. deche

    I’m running Clojure 1.4 and leiningen 2.0
    when I tried to run (start 8888) , I got:
    CompilerException java.lang.RuntimeException: Unable to resolve symbol: start in this context, compiling:(NO_SOURCE_PATH:1)

  13. Alex Nelson

    I think a more idiomatic approach to writing the start function would be:

    ;;; start function for starting jetty
    (defn start
    ([] (start 8080)) ; if no port specified, just use 8080
    ([port] (run-jetty #’routes {:port port :join? false})))

    But overall, yeah, a great intro :)

Leave a Reply