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
550
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
270
Other Decks in Programming
See All in Programming
Generative AI Use Cases JP (略称:GenU)奮闘記
hideg
1
290
Jakarta EE meets AI
ivargrimstad
0
120
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
2
1.1k
Tauriでネイティブアプリを作りたい
tsucchinoko
0
370
ペアーズにおけるAmazon Bedrockを⽤いた障害対応⽀援 ⽣成AIツールの導⼊事例 @ 20241115配信AWSウェビナー登壇
fukubaka0825
6
1.8k
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
100
現場で役立つモデリング 超入門
masuda220
PRO
15
3.2k
最新TCAキャッチアップ
0si43
0
140
ヤプリ新卒SREの オンボーディング
masaki12
0
130
AWS Lambdaから始まった Serverlessの「熱」とキャリアパス / It started with AWS Lambda Serverless “fever” and career path
seike460
PRO
1
250
Jakarta EE meets AI
ivargrimstad
0
510
Pinia Colada が実現するスマートな非同期処理
naokihaba
4
220
Featured
See All Featured
Art, The Web, and Tiny UX
lynnandtonic
297
20k
10 Git Anti Patterns You Should be Aware of
lemiorhan
654
59k
Building Applications with DynamoDB
mza
90
6.1k
The World Runs on Bad Software
bkeepers
PRO
65
11k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
5 minutes of I Can Smell Your CMS
philhawksworth
202
19k
Building Adaptive Systems
keathley
38
2.3k
BBQ
matthewcrist
85
9.3k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
Designing the Hi-DPI Web
ddemaree
280
34k
Teambox: Starting and Learning
jrom
133
8.8k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.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