views:

9974

answers:

6

I suppose this is a strange question to the huge majority of programmers that work daily with Java. I don't. I know Java-the-language, because I worked on Java projects, but not Java-the-world. I never made a web app from scratch in Java. If I have to do it with Python, Ruby, I know where to go (Django or Rails), but if I want to make a web application in Clojure, not because I'm forced to live in a Java world, but because I like the language and I want to give it a try, what libraries and frameworks should I use?

A: 

Since Clojure programs can invoke Java, it should be relatively easy to build a web framework. Just googling for "clojure web framework" seems to return several Opensource efforts to build a web framework for Clojure. Maybe you could give one of those a try?

Harish
Interestingly enough, two years later after the answer, googling that yields this s.o. question as the first result.
Marcelo Morales
+15  A: 

Frameworks are overrated. Make a servlet and a JSP page and learn the real way! Also, use notepad for maximum manliness. I suggest not shaving for a few weeks before-hand.

MattC
Awww, come on! It was just a joke!
MattC
> I suggest not shaving for a few weeks before-handAnd thus the "The scary beard framework" is born.
swapnonil
Dude, I think Perl had scary beard framework since ~1996.
aaron
It's funny that people are still down-voting this.
MattC
I up-voted this not because it is good advice, but because it is hilarious.
ecounysis
"Frameworks are overrated" then "use servlet"? Deary me. The truly bearded would get straight down to protocol.
Jim Downing
+22  A: 

By far the best Clojure web framework I have yet encountered is Compojure: http://github.com/weavejester/compojure/tree/master

It's small but powerful, and has beautifully elegant syntax. (It uses Jetty under the hood, but it hides the Servlet API from you unless you want it, which won't be often). Go look at the README at that URL, then download a snapshot and start playing.

while it's easy to include libs this way... dependency creep is not a good thing. You need balance. But this is nuts!
Richard
Was Richard's comment meant for this answer? I don't understand it.
John Cromartie
+8  A: 

Webjure, a web programming framework for Clojure.

Features: Dispatch servlet calls Clojure functions. Dynamic HTML generation. SQL query interface (through JDBC).

This answer is meant as a placeholder for Webjure information.

J. Pablo Fernández
I'm not sure this is a good example either. While the codebase seems shallow(good) there is enough written in java that it seems to miss the mark. I would have expected a pure clojure framework.
Richard
+5  A: 

Compojure's what I used to build a tiny blogging application. It's modeled on Sinatra, which is a minimal, light-weight web framework for Ruby. I mostly just used the routing, which is just like Sinatra's. It looks like:

(GET "/post/:id/:slug"
  (some-function-that-returns-html :id :slug))

There's no ORM or templating library, but it does have functions that turn vectors into HTML.

Joe W.
+17  A: 

Compojure is no longer a complete framework for developing web applications. Since the 0.4 release, compojure has been broken off into several projects.

Ring provides the foundation by abstracting away the HTTP request and response process. Ring will parse the incoming request and generate a map containing all of the parts of the request such as uri, server-name and request-method. The application will then handle the request and based on the request generate a response. A response is represented as a map containing the following keys: status, headers, and body. So a simple application would look like:

(def app [req]
  (if (= "/home" (:uri req))
    {:status 200
     :body "<h3>Welcome Home</h3>"}
    {:status 200 
     :body "<a href='/home'>Go Home!</a>"}))

One other part of Ring is the concept of middle-ware. This is code that sits between the handler and the incoming request and/or the outgoing response. Some built in middle-ware include sessions and stacktrace. The session middle-ware will add a :session key to the request map that contains all of the session info for the user making the request. If the :session key is present in the response map, it will be stored for the next request made by the current user. While the stack trace middle-ware will capture any exceptions that occur while processing the request and generate a stack trace that is sent back as the response if any exceptions do occur.

Working directly with Ring can be tedious, so Compojure is built on top of Ring abstracting away the details. The application can now be expressed in terms of routing so you can have something like this:

(defroutes my-routes
  (GET "/" [] "<h1>Hello all!</h1>")
  (GET "/user/:id" [id] (str "<h1>Hello " id "</h1>")))

Compojure is still working with the request/response maps so you can always access them if needed:

(defroutes my-routes
  (GET "*" {uri :uri} 
           {:staus 200 :body (str "The uri of the current page is: " uri)}))

In this case the {uri :uri} part accesses the :uri key in the request map and sets uri to that value.

The last component is Hiccup which makes generating the html easier. The various html tags are represented as vectors with the first element representing the tag name and the rest being the body of the tag. "<h2>A header</h2>" becomes [:h2 "A Header"]. The attributes of a tag are in an optional map. "<a href='/login'>Log In Page</a>" becomes [:a {:href "/login"} "Log In Page"]. Here is a small example using a template to generate the html.

(defn layout [title & body]
  (html
    [:head [:title title]]
    [:body [:h1.header title] body])) 

(defn say-hello [name]
  (layout "Welcome Page" [:h3 (str "Hello " name)]))

(defn hiccup-routes
  (GET "/user/:name" [name] (say-hello name)))

Here is a link to a rough draft of some documentation currently being written by the author of compojure that you might find helpful: Compojure Doc

Ross Goddard