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
540
Clojure Web Development
pschirmacher
June 11, 2013
Tweet
Share
More Decks by pschirmacher
See All by pschirmacher
HTTP with Java 8
pschirmacher
0
130
Clojure Reducers
pschirmacher
1
260
Other Decks in Programming
See All in Programming
Designing for tomorrow's programming workflows
honnibal
PRO
2
130
サイコロで理解する統計的仮説検定の考え方
tatamiya
4
910
Hanami and htmx
bkuhlmann
0
210
Ruby GitHub Packages
bkuhlmann
0
630
単体テストを書かない技術 #phpcon_odawara
o0h
PRO
26
8.2k
Rails と人魚の話/rails-and-mermaid
sanfrecce_osaka
0
100
Goのエラースタックトレースの歴史と今後
sonatard
7
1.2k
Zero Waste, Radical Magic, and Italian Graft – Quarkus Efficiency Secrets
hollycummins
0
230
効率化に挑戦してみたらモバイル開発が少し快適になった話
ryunakayama
0
130
Code Reviews
bkuhlmann
4
890
Git Lint
bkuhlmann
4
750
try!Swift Tokyo 2024 参加報告 LT
akidon0000
1
220
Featured
See All Featured
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
274
13k
Agile that works and the tools we love
rasmusluckow
325
20k
A better future with KSS
kneath
231
16k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
352
28k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
221
21k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
20
1.9k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
322
20k
StorybookのUI Testing Handbookを読んだ
zakiyama
13
4.6k
jQuery: Nuts, Bolts and Bling
dougneiner
59
7.1k
Fashionably flexible responsive web design (full day workshop)
malarkey
398
65k
Designing Experiences People Love
moore
136
23k
Designing with Data
zakiwarfel
96
4.8k
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