DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
  1. DZone
  2. Coding
  3. Java
  4. Web application in Clojure: the starting point

Web application in Clojure: the starting point

Giorgio Sironi user avatar by
Giorgio Sironi
·
Jan. 05, 12 · Interview
Like (0)
Save
Tweet
Share
9.80K Views

Join the DZone community and get the full member experience.

Join For Free

Ring is a basic tool for executing your Clojure code into a web server environment, by satisfying HTTP requests and producing responses. In scope, Ring is similar to the Servlet API, but it's not as standard and diffused; by the way, servlets are always used internally by Clojure implementations of the HTTP stack.

There are other open source tools for Clojure web development, that use Ring as a component, such as Compojure. There are even full-stack frameworks like Noir, but in this article we'll stick to the simple API of Ring and leave more elaborated approaches for later. Links to the code shown in this article are included in the Resources section.

Hello World

Clojure projects use Leiningen *link* to pull in dependencies and to run their code. Leiningen is a wrapper for Ant and Maven that will fetch JARs for you and execute the test suite or the application itself.

In a Leiningen-enabled project, the project.clj file defines dependencies:

(defproject clojure-web-hello-world-ring "1.0.0-SNAPSHOT"
  :description "Web application Hello World with Clojure"
  :dependencies [[org.clojure/clojure "1.2.1"]
                 [ring/ring "1.0.1"]]
  :main clojure-web-hello-world-ring.core)

The first two lines specify a name, a version and a description; these are non-functional properties in this example and you can put there anything.

The :dependencies key specifies what to pull in: in this case, the Facade project for ring which will depend in turn both on production code facilities like Jetty and on developers tools.

Finally, project.clj specifies the name of the namespace where the -main function resides: this function will be called with lein run.

The src/clojure-web-hello-world-ring/core.clj defines the actual code to run:

(ns clojure-web-hello-world-ring.core
    (:use ring.adapter.jetty))
(defn app [req]
    {:status 200
     :headers {"Content-Type" "text/html"}
     :body    "Hello World!"})
(defn -main [] (run-jetty #'app {:port 8080}))

The dependency we import is ring.adapter.jetty, a wrapper over the Jetty embedded servlet container which will run our code.

We also define a function, app, which takes as an argument a request map and returns a response map. These two are plain old Clojure data structures.

The -main function starts Jetty on port 8080 and tells it to handle all request with this simple handler, which just outputs "Hello World!".

Slightly more complex example

Now that we have bridged a Servlet container with Clojure code you have a Turing-complete web application: you can build anything with this pattern (although other libraries may save you time.)

As an example, let's serve more than one kind of request:

(ns clojure-web-hello-world-ring.core
    (:use ring.adapter.jetty)
    (:use clojure.string))
(defn extract-name [uri]
    (replace-first uri "/" ""))
(defn app [req]
    {:status 200
     :headers {"Content-Type" "text/html"}
     :body    (if (= (:uri req) "/")
                  "Hello, World!"
                  (str "Hello, " (extract-name (:uri req)) "!"))})
(defn -main [] (run-jetty #'app {:port 8080}))

Now http://localhost:8080 will show "Hello, World!". http://localhost:8080/giorgio (or any other name) will show "Hello, giorgio!" instead.

Further resources

The sample code for this article is on Github; if you go back one revision in the history you'll find also the first Hello World example. To run the code, remember to run both lein deps and lein run after the cloning.

Ring contains a small specification describing all the keys available in the request and response maps.

This a bit outdated tutorial (for Clojure 1.1 and Ring 0.2) shows how to setup some developer tools for continuously reloading code during development and displaying stack traces in the browser.

The Ring API documentation (updated to 1.0.0) describes all the available namespaces if you pull in ring/ring with Leiningen.

Conclusions

We have only scratched the surface of Ring, but it is a very low-level library anyway, which works close to the HTTP request.

We will need more tools to get at least a Servlet API equivalent, with routing of requests and parsing of parameters from the GET query string. In the next articles we will see how Compojure can be used over Ring to quickly build web applications in the same way as Sinatra and Spark work.

Web application Clojure

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How to Submit a Post to DZone
  • DZone's Article Submission Guidelines
  • Spring Boot vs Eclipse Micro Profile: Resident Set Size (RSS) and Time to First Request (TFR) Comparative
  • Unlocking the Power of Elasticsearch: A Comprehensive Guide to Complex Search Use Cases

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: