Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Clojure Web Development
Search
pschirmacher
June 11, 2013
Programming
2
590
Clojure Web Development
pschirmacher
June 11, 2013
Tweet
Share
More Decks by pschirmacher
See All by pschirmacher
HTTP with Java 8
pschirmacher
0
140
Clojure Reducers
pschirmacher
1
280
Other Decks in Programming
See All in Programming
AIと”コードの評価関数”を共有する / Share the "code evaluation function" with AI
euglena1215
1
150
5つのアンチパターンから学ぶLT設計
narihara
1
160
Google Agent Development Kit でLINE Botを作ってみた
ymd65536
2
240
0626 Findy Product Manager LT Night_高田スライド_speaker deck用
mana_takada
0
160
Blazing Fast UI Development with Compose Hot Reload (droidcon New York 2025)
zsmb
1
290
プロダクト志向ってなんなんだろうね
righttouch
PRO
0
180
明示と暗黙 ー PHPとGoの インターフェイスの違いを知る
shimabox
2
490
猫と暮らす Google Nest Cam生活🐈 / WebRTC with Google Nest Cam
yutailang0119
0
110
Azure AI Foundryではじめてのマルチエージェントワークフロー
seosoft
0
160
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
240
Kotlin エンジニアへ送る:Swift 案件に参加させられる日に備えて~似てるけど色々違う Swift の仕様 / from Kotlin to Swift
lovee
1
270
システム成長を止めない!本番無停止テーブル移行の全貌
sakawe_ee
1
180
Featured
See All Featured
Designing for humans not robots
tammielis
253
25k
Navigating Team Friction
lara
187
15k
Facilitating Awesome Meetings
lara
54
6.4k
A Modern Web Designer's Workflow
chriscoyier
694
190k
The Pragmatic Product Professional
lauravandoore
35
6.7k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
Embracing the Ebb and Flow
colly
86
4.7k
Mobile First: as difficult as doing things right
swwweet
223
9.7k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
138
34k
How GitHub (no longer) Works
holman
314
140k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.4k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Transcript
We'll take care of it. Personally. Clojure Web Development Philipp
Schirmacher | innoQ Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH http://upload.wikimedia.org/wikip Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Clojure http://upload.wikimedia.org/wikipedia/en/1/1a/Clo A practical Lisp
variant for the JVM Functional programming Dynamic Typing Full-featured macro system Bi-directional Java interop Immutable data structures Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Lisp?? Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Lots of irritating silly parentheses
Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Clojure Environment Clojuresque (Gradle) Leiningen
Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH http://www.tbray.org/ongoing/When/200x/2008/09/25/-big/R0010774.jpg.html Rich Hickey Tuesday, June
11, 13
© 2013 innoQ Deutschland GmbH Clojure Crash Course Tuesday, June
11, 13
© 2013 innoQ Deutschland GmbH Generic Data Types Tuesday, June
11, 13
© 2013 innoQ Deutschland GmbH {:name "Clojure" :features [:functional :jvm
:parens] :creator "Rich Hickey" :stable-version {:number "1.5.1" :release "2013/03/10"}} Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Functions Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (:city {:name "innoQ" :city "Monheim"})
> "Monheim" (map inc [1 2 3]) > (2 3 4) (+ 1 2) > 3 Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (fn [x y] (+ x
y)) ((fn [x y] (+ x y)) 1 2) > 3 (def add (fn [x y] (+ x y))) (defn add [x y] (+ x y)) (add 1 2) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn activity [weather] (if (nice?
weather) :surfing :playstation)) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn make-adder [x] (fn [y]
(+ x y))) (def add-two (make-adder 2)) (add-two 3) > 5 Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Web Development? Tuesday, June 11,
13
© 2013 innoQ Deutschland GmbH app request response data function
Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Ring Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn hello-world-app [req] {:status 200
:headers {"Content-Type" "text/plain"} :body "Hello, World!"}) (hello-world-app {:uri "/foo" :request-method :get}) > {...} (run-jetty hello-world-app {:port 8080}) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn my-first-homepage [req] {:status 200
:headers {"Content-Type" "text/html"} :body (str "<html><head>" "<link href=\"/pretty.css\" ...>" "</head><body>" "<h1>Welcome to my Homepage</h1>" (java.util.Date.) "</body></html>")}) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH static resources request response homepage
Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn decorate [webapp] (fn [req]
...before webapp... (webapp req) ...after webapp...)) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn decorate [webapp] (fn [req]
(if (static-resource? req) (return-resource req) (webapp req)))) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn wrap-resource [handler root-path] (fn
[request] (if-not (= :get (:request-method request)) (handler request) (let [path (extract-path request)] (or (resource-response path {:root root-path}) (handler request)))))) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn my-first-homepage [req] ...) (def
webapp (wrap-resource my-first-homepage "public")) (run-jetty webapp {:port 8080}) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (webapp {:uri "/pretty.css" :request-method :get
:headers {}}) > {:status 200 :headers {} :body #<File ...resources/public/pretty.css>} Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH wrap-resource request response my- rst-homepage
wrap- le-info Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn homepage [req] ...) (def
webapp (-> homepage (wrap-resource "public") wrap-file-info)) (run-jetty webapp {:port 8080}) (wrap-file-info (wrap-resource homepage "public")) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (webapp {:uri "/pretty.css" :request-method :get
:headers {}}) > {:status 200 :headers {"Content-Length" "16" "Last-Modified" "Thu, 14 Jun ..." "Content-Type" "text/css"} :body #<File ...resources/public/pretty.css>} Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH wrap-resource wrap- le wrap-params wrap-session
wrap-flash wrap-etag wrap-basic-authentication Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH middleware request response handler middleware
routing ... Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Compojure Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (def get-handler (GET "/hello" []
"Hello, World!")) (get-handler {:request-method :get :uri "/hello"}) > {:body "Hello, World!" ...} (get-handler {:request-method :post :uri "/hello"}) > nil Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (def get-handler (GET "/hello/:name" [name]
(str "Hello, " name "!"))) (def post-handler (POST "/names" [name] (remember name) (redirect (str "/hello/" name)))) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Digression: Macros Tuesday, June 11,
13
© 2013 innoQ Deutschland GmbH text Compiler bytecode Tuesday, June
11, 13
© 2013 innoQ Deutschland GmbH text Reader Evaluator data structures
bytecode (if true (print "true" (print "false")) “(if true (print "true" (print "false"))” Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH text Reader Evaluator data structures
bytecode (cond (< 4 3) (print "wrong") (> 4 3) (print "yep")) (if (< 4 3) (print "wrong") (if (> 4 3) (print "yep") nil)) cond- Macro (cond (< 4 3) (pri... (> 4 3) (pri... “(cond (< 4 3) (print "wrong") (> 4 3) (print "yep"))” Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defmacro my-cond [c1 e1 c2
e2] (list 'if c1 e1 (list 'if c2 e2 nil))) (my-cond false (println "won't see this") true (println "it works!")) it works! Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (my-cond false (println "won't see
this") true (println "it works!")) it works! (defmacro my-cond [c1 e1 c2 e2] `(if ~c1 ~e1 (if ~c2 ~e2 nil))) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH text Reader Evaluator data structures
bytecode (GET "/hello" [] "Hello, World!") (fn [req] (if (and (match (:uri req) "/hello") (= (:request-method req) :get)) {:body "Hello, World!" …} nil)) GET- Macro “(GET "/hello" [] "Hello, World!")” Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Back to Compojure... Tuesday, June
11, 13
© 2013 innoQ Deutschland GmbH (def get-handler (GET "/hello/:name" [name]
(str "Hello, " name "!"))) (def post-handler (POST "/names" [name] (remember name) (redirect (str "/hello/" name)))) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defroutes todo-app (GET "/todos" []
(render (load-all-todos))) (GET "/todos/:id" [id] (render (load-todo id))) (POST "/todos" {json-stream :body} (create-todo (read-json (slurp json-stream))) (redirect "/todos"))) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defroutes more-routes (context "/todos/:id" [id]
(DELETE "/" [] (delete-todo id) (redirect "/todos")) (PUT "/" {json-stream :body} (update-todo (read-json (slurp json-stream))) (redirect (str "/todos/" id))))) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defroutes complete-app todo-app more-routes (not-found
"Oops.")) (def secure-app (wrap-basic-authentication complete-app allowed?)) (run-jetty (api secure-app) {:port 8080}) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH middleware request response handler middleware
routing ... JSON HTML Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Hiccup Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH <element attribute="foo"> <nested>bar</nested> </element> [:element]
Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH <element attribute="foo"> <nested>bar</nested> </element> [:element
{:attribute "foo"}] Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH <element attribute="foo"> <nested>bar</nested> </element> [:element
{:attribute "foo"} [:nested]] Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH <element attribute="foo"> <nested>bar</nested> </element> [:element
{:attribute "foo"} [:nested "bar"]] Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH <html> <head><title>Foo</title></head> <body><p>Bar</p></body> </html> (def
hiccup-example [:html [:head [:title "Foo"]] [:body [:p "Bar"]]]) (html hiccup-example) > "<html>...</html>" Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (def paul {:name "Paul" :age
45}) (defn render-person [person] [:dl [:dt "Name"] [:dd (:name person)] [:dt "Age"] [:dd (:age person)]]) (html (render-person paul)) > "<dl><dt>Name</dt><dd>Paul</dd>...</dl>" Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (defn render-person [person] [:dl [:dt
"Name"] [:dd (:name person)] [:dt "Age"] [:dd (:age person)]]) (defn people-page [people] [:html [:head [:title "All the people"]] [:body (map render-person people)]]) Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH (link-to "http://www.innoq.com" "click here") >
[:a {:href "http://www.innoq.com"} "click here"] (form-to [:post "/login"] (text-field "Username") (password-field "Password") (submit-button "Login")) > [:form {:action "POST" ...} [:input ...] ...] Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH <div id="my-id" class="class1 class2"> foo
</div> [:div#my-id.class1.class2 "foo"] Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH middleware request response handler middleware
routing ... JSON HTML Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH middleware {} {} handler middleware
routing ... JSON HTML servlet adapter javax.servlet.http. HttpServletRequest javax.servlet.http. HttpServletRespone Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Conclusion Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH :-) ‣ Simple basic concepts
‣ Easy to use ‣ Little code (also in libraries) ‣ Helpful community ‣ Mature eco system Tuesday, June 11, 13
Thank you! We'll take care of it. Personally. © 2012
innoQ Deutschland GmbH Philipp Schirmacher philipp.schirmacher@innoq.com @pschirmacher Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Backup Tuesday, June 11, 13
© 2013 innoQ Deutschland GmbH Task Libraries HTTP Basics Ring
Routing Compojure Moustache HTML Hiccup Enlive Persistence clojure.java.jdbc Korma Monger Asynchronous Server Aleph JavaScript ClojureScript Tuesday, June 11, 13