Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Clojure Web Development
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
pschirmacher
June 11, 2013
Programming
670
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Clojure Web Development
pschirmacher
June 11, 2013
More Decks by pschirmacher
See All by pschirmacher
HTTP with Java 8
pschirmacher
0
150
Clojure Reducers
pschirmacher
1
290
Other Decks in Programming
See All in Programming
A2UI for Android: Safely Rendering AI-Generated UI with Jetpack Compose - DroidKaigi 2026
itsmedreamwalker
0
110
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
230
技術的負債を組織課題として解く-増えすぎたマイクロサービスとの戦い-
reimaru
1
1.2k
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
150
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
4.2k
【DroidKaigi 2026】「アクセシビリティを利用するとき、 アクセシビリティもまたこちらを利用している」 〜マルウェアによる攻撃と防衛について〜
halunoyo
0
460
新卒PdEのリアル
ryu1013
1
490
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
3
340
From 6 People Classroom Meetup to 100 People Regional Conference / FOSS4G Hiroshima 2026
furukawayasuto
0
170
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
190
Kiroで創り、AgentCoreで繋ぐ!AWSで実践する「AI-DLC」から「AIエージェント統合」までの最新地図
licux
4
670
Webの地図
yosuke_furukawa
PRO
6
4.4k
Featured
See All Featured
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2.1k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
202
76k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
300
Measuring & Analyzing Core Web Vitals
bluesmoon
9
990
Deep Space Network (abreviated)
tonyrice
0
300
The untapped power of vector embeddings
frankvandijk
2
1.9k
Product Roadmaps are Hard
iamctodd
55
13k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
330
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.2k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
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
[email protected]
@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