Mature Clojure web frameworks? [closed]
Asked Answered
O

5

48

What are the current choices of mature Clojure web frameworks? I am looking for some kind of feature matrix telling me what the popular frameworks support and to what extent, including:

  • Response templating (response written in Clojure or in some other markup - e.g. like JSP with Tiles)
  • HTTP sessions
  • REST with automatic mapping of URLs into action-functions and params
  • HTML forms (params available as map, error handling, validation)
  • Application flow (known from Java frameworks - request handlers return action identifiers which are eventually handled by renderers)
Offcenter answered 23/8, 2010 at 21:22 Comment(1)
-1 for asking for HTTP sessions - the Play framework proves you don't need thatOwner
M
33

Perhaps my answer to the What is the good starting point to developing RESTful web service in Clojure? question on SO might be of help to you. It mentions some important web libraries for Clojure (with links and short summaries). The key point which I would like to reiterate here is stated in the first paragraph of that answer:

First of all, I think that you are unlikely to find a single shrinkwrapped solution to do all this in Clojure (except in the form of a Java library to be used through interop). What is becoming Clojure's standard Web stack comprises a number of libraries which people mix and match in all sorts of ways (since they happily tend to be perfectly compatible).

To that I would add that you should probably not expect to handle things with the sort of "application flow" you might know from Java (or if you believe you really need it, you'll probably have to roll your own lib to support it!). That's alright, though, as people seem to be very happy with Ring's handler-is-a-function, higher-order-middleware-friendly approach.


To address your bullets:

  • Response templating:
    There is a number of Clojure-specific solutions, including Enlive and Hiccup (Enlive is a very powerful HTML scraping / templating / transforming engine; Hiccup is a DSL for writing HTML in Clojure with the nice property that it renders fast). Also, this is probably one place where it makes perfect sense to drop down to Java and use something like, say, StringTemplate. This even has the good side of discouraging the mixing of templates and logic! (I believe Stuart Halloway has mentioned that Relevance -- his company -- is using this strategy in their work and having great success with it.)

  • HTTP sessions
    That would be Sandbar, I suppose. The author has started a series of blogposts about it which looks very promising.

  • REST with automatic mapping of URLs into action-functions and params
    That's Ring & Compojure and/or Moustache. See below.

  • HTML forms (params available as map, error handling, validation)
    As above.

  • Application flow (known from Java frameworks - request handlers return action identifiers which are eventually handled by renderers)
    As mentioned above, not really something people tend to do in Clojure.


As a starting point in learning about the Clojure web stack, this Ring tutorial by Ring's author Mark McGranaghan is very helpful. Compojure's author James Reeves has some documentation on Compojure. Perhaps my recent answer to the What’s the “big idea” behind compojure routes? question might be of help too. Ring's sources also include a great SPEC document.

Mafala answered 23/8, 2010 at 22:49 Comment(6)
would you mind expanding a bit on the issue of templating options, and why you might recommend 'dropping down into java'? Is it an issue of the maturity of functionality, of performance, or something else?Amp
@Rob Lachlan: I wouldn't necessarily recommend dropping down to Java -- I just think that this is one task where doing so might not necessarily lead to an inferior experience. If you structure your application so that your template engine never calls out to your application logic at the rendering stage, what difference does it make if it's written in Java / Scala / whatever? At least as long as there is a sane way of setting template variables, of course (e.g. StringTemplate uses .setAttribute on templates, which is simple enough to use with doseq and a map from Clojure).Overlooker
That is not to say that there are no reasons to prefer pure Clojure templating schemes -- I'm not sure I know of anything quite like Enlive outside of Clojure land, for example (but working wonders costs time, so it might not be the appropriate choice where something significantly simpler would do perfectly well), Hiccup is a great HTML-producing DSL (but is there much point to teaching a designer to write Hiccup when they already know another JVM solution which you can just call out to?) etc.Overlooker
I believe that in the case of this particular answer I simply thought that if the OP is used to Web development in Java, he may well be perfectly happy with whichever JVM templating engine he would normally use. Plus I can't really think of a direct equivalent to StringTemplate in Clojure (nor can I see much of a reason to invent one) and it seems to be a great solution for HTML templating.Overlooker
Good points all, thank you. That clarified things for me a bit -- I've come to the conclusion that, at least for my personal projects, I'm going to using straight hiccup. After all, since our language's syntactic form is isomorphic with xml and html (or very nearly), it would seem a shame not too exploit that fact.Amp
I've made a full stack framework for clojure: coast on clojure It's still young, which is why I left a comment and not an answer since it's not technically mature (still lacking in a few areas where other full stack frameworks shine). Check it out and see if solves the problem!Deglutinate
A
14

Since this question was originally asked / answered, the Noir web framework has emerged as a promising solution.

It uses hiccup for the templating part, but offers a more complete framework around that.

Basic code sample from the Noir main page:

(ns my-app
  (:use noir.core)
  (:require [noir.server :as server]))

(defpage "/welcome" []
    "Welcome to Noir!")

(server/start 8080)
Ablation answered 28/11, 2011 at 5:25 Comment(1)
Noir is now deprecated, but see lib-noirSorrell
A
8

I will recommend you to use Luminus, not because of its awesome name, but also its feature.

And since Noir is no longer maintained, I won't recommend you to use that. It is also a good choice to start from ring & Compojure from the very beginning to build your own framework.

Aphis answered 26/11, 2013 at 1:3 Comment(0)
M
1

You may be asking the wrong question. What I'm seeing in your question is "what Clojure framework is most like the Java Object-Oriented frameworks I'm used to?". There is no good answer to that; if you only feel comfortable with a state-ful server-side approach (such as Grails or Tapestry) then perhaps you should stay there, and find a way to implement some of your backend in Clojure.

On the other hand, if you want to build something more true to Clojure, you may want to find your own mix. I've had some good success using AngularJS and CoffeeScript on the client, and Clojure (using Ring and Bishop) on the server (though we are moving from Bishop to Liberator). In any case, once you embrace the "single page" web app approach and start treating the server-side as a source and sink of data, you'll find Clojure works exceptionally well.

Mokas answered 3/1, 2014 at 22:21 Comment(0)
D
1

try road framework for fast web dev https://github.com/zhujinxian/road

(defn render-test [ret tmt]
  (-> (resp/response "------render----test------") 
    (#(resp/content-type %1 "text/plain"))))

(defn foo
  "I don't do a whole lot."
  [x]
  (str "来自源码目录的参数:" x))

(defn handler [^Integer x]
    {:$r render-test :text (str "hello world, road goes sucess!" (foo x))})

(defn home [req content ^Integer num]
    {:hiccup "home.clj" :content (str "home" content) :num num})

(defroad road (GET "/web-test-0.1.0-SNAPSHOT-standalone/main" handler) 
              (GET "/web-test-0.1.0-SNAPSHOT-standalone/home/:num{\\d+}" home))

(defn -main [& args]
  (log/info "---------log4j test-------")
  (jetty/run-jetty road {:port 3000}))
Demonstrator answered 8/3, 2015 at 3:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.