I would say the best place to start is:
- Using duct, and write your application server side in Clojure only. Do not touch ClojureScript yet.
- If you needed at some point to write separate application services, I would use Pedestal.
But, I’ll even suggest something completely different and unorthodox. Use a Java framework, and add some Clojure to it. One of:
For each Java controller, have a similar Clojure controller, and in the Java controller, just call into the Clojure one.
For example, in Spring MVC:
Inside SomeJavaController.java:
ModelAndView mv = new ModelAndView("someView.jsp");
IFn someClojureController = Clojure.var("namespace.to.your.clojure.controllers.some-clojure-controller", "render-page");
mv.addObject("clojure", someClojureController.invoke(requestParam1, requestParam2, ...));
return mv;
For each JSP page, just have the JSP template be: ${clojure}
. And Now in your Clojure controller, return the full HTML, and have the Java controller just send the full HTML returned by the Clojure controller onto the model as clojure
.
Inside someView.jsp:
${clojure}
Now in your Clojure controller, I recommend you use Hiccup for HTML templating. Here’s hello world:
Inside some-clojure-controller.clj:
(ns namespace.to.your.clojure.controllers.some-clojure-controller
(:require [hiccup.core :as hc]
[hiccup.def :as hd]
[hiccup.element :as he]
[hiccup.form :as hf]
[hiccup.page :as hp]
[hiccup.util :as hu])
(hd/defhtml hello-world-page
[first-name last-name]
(hp/html5
[:head [:title "A Clojure Spring MVC Hello World!"]]
[:body
[:p "Hello " first-name ", " last-name "!"]]))
(defn render-page
[request-param1 request-param2 ...]
;; This assumes request-param1 and 2 were first and last names.
(hello-world-page request-param1 request-param2)
That said, since you are just starting, I might even just use JSP for now as your template language. When you call your Clojure controller namespace from the Java controller, just pass it the model, and have it return the model. And template your HTML using JSP. As such:
Inside SomeJavaController.java:
ModelAndView mv = new ModelAndView("someView.jsp");
IFn someClojureController = Clojure.var("namespace.to.your.clojure.controllers.some-clojure-controller", "render-page");
return someClojureController.invoke(mv, requestParam1, requestParam2, ...);
Inside some-clojure-controller.clj:
(ns namespace.to.your.clojure.controllers.some-clojure-controller)
(defn render-page
[mv request-param1 request-param2 ...]
;; This assumes request-param1 and 2 were first and last names.
(doto mv
(.addObject "first-name" request-param1)
(.addObject "last-name" request-param2)))
Inside someView.jsp:
<!DOCTYPE html">
<html>
<head>
<title>A Clojure Hello World, using JSP for the templating.</title>
</head>
<body>
<p>Hello ${first-name}, ${last-name}!</p>
</body>
</html>
The advantage of this approach is that Spring MVC and Apache Struts are very well documented, compared to Clojure frameworks. They are also very simple, old, tested, proven frameworks, with no fancy bells and whistles. A good overall place to start.
The choice is yours.
P.S.: Shout out to coast as well. It can also be a good place to start for a beginner, has good-ish docs, though it’s quite new (maybe incomplete in some aspects?).