Clojure Web Development

Clojure Web Development

A0335428a9bc84ac981640853ca3a7eb?s=128

pschirmacher

June 11, 2013
Tweet

Transcript

  1. We'll take care of it. Personally. Clojure Web Development Philipp

    Schirmacher | innoQ Tuesday, June 11, 13
  2. © 2013 innoQ Deutschland GmbH http://upload.wikimedia.org/wikip Tuesday, June 11, 13

  3. © 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
  4. © 2013 innoQ Deutschland GmbH Lisp?? Tuesday, June 11, 13

  5. © 2013 innoQ Deutschland GmbH Lots of irritating silly parentheses

    Tuesday, June 11, 13
  6. © 2013 innoQ Deutschland GmbH Clojure Environment Clojuresque (Gradle) Leiningen

    Tuesday, June 11, 13
  7. © 2013 innoQ Deutschland GmbH http://www.tbray.org/ongoing/When/200x/2008/09/25/-big/R0010774.jpg.html Rich Hickey Tuesday, June

    11, 13
  8. © 2013 innoQ Deutschland GmbH Clojure Crash Course Tuesday, June

    11, 13
  9. © 2013 innoQ Deutschland GmbH Generic Data Types Tuesday, June

    11, 13
  10. © 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
  11. © 2013 innoQ Deutschland GmbH Functions Tuesday, June 11, 13

  12. © 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
  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
  14. © 2013 innoQ Deutschland GmbH (defn activity [weather] (if (nice?

    weather) :surfing :playstation)) Tuesday, June 11, 13
  15. © 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
  16. © 2013 innoQ Deutschland GmbH Web Development? Tuesday, June 11,

    13
  17. © 2013 innoQ Deutschland GmbH app request response data function

    Tuesday, June 11, 13
  18. © 2013 innoQ Deutschland GmbH Ring Tuesday, June 11, 13

  19. © 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
  20. © 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
  21. © 2013 innoQ Deutschland GmbH static resources request response homepage

    Tuesday, June 11, 13
  22. © 2013 innoQ Deutschland GmbH (defn decorate [webapp] (fn [req]

    ...before webapp... (webapp req) ...after webapp...)) Tuesday, June 11, 13
  23. © 2013 innoQ Deutschland GmbH (defn decorate [webapp] (fn [req]

    (if (static-resource? req) (return-resource req) (webapp req)))) Tuesday, June 11, 13
  24. © 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
  25. © 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
  26. © 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
  27. © 2013 innoQ Deutschland GmbH wrap-resource request response my- rst-homepage

    wrap- le-info Tuesday, June 11, 13
  28. © 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
  29. © 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
  30. © 2013 innoQ Deutschland GmbH wrap-resource wrap- le wrap-params wrap-session

    wrap-flash wrap-etag wrap-basic-authentication Tuesday, June 11, 13
  31. © 2013 innoQ Deutschland GmbH middleware request response handler middleware

    routing ... Tuesday, June 11, 13
  32. © 2013 innoQ Deutschland GmbH Compojure Tuesday, June 11, 13

  33. © 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
  34. © 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
  35. © 2013 innoQ Deutschland GmbH Digression: Macros Tuesday, June 11,

    13
  36. © 2013 innoQ Deutschland GmbH text Compiler bytecode Tuesday, June

    11, 13
  37. © 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
  38. © 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
  39. © 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
  40. © 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
  41. © 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
  42. © 2013 innoQ Deutschland GmbH Back to Compojure... Tuesday, June

    11, 13
  43. © 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
  44. © 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
  45. © 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
  46. © 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
  47. © 2013 innoQ Deutschland GmbH middleware request response handler middleware

    routing ... JSON HTML Tuesday, June 11, 13
  48. © 2013 innoQ Deutschland GmbH Hiccup Tuesday, June 11, 13

  49. © 2013 innoQ Deutschland GmbH <element attribute="foo"> <nested>bar</nested> </element> [:element]

    Tuesday, June 11, 13
  50. © 2013 innoQ Deutschland GmbH <element attribute="foo"> <nested>bar</nested> </element> [:element

    {:attribute "foo"}] Tuesday, June 11, 13
  51. © 2013 innoQ Deutschland GmbH <element attribute="foo"> <nested>bar</nested> </element> [:element

    {:attribute "foo"} [:nested]] Tuesday, June 11, 13
  52. © 2013 innoQ Deutschland GmbH <element attribute="foo"> <nested>bar</nested> </element> [:element

    {:attribute "foo"} [:nested "bar"]] Tuesday, June 11, 13
  53. © 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
  54. © 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
  55. © 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
  56. © 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
  57. © 2013 innoQ Deutschland GmbH <div id="my-id" class="class1 class2"> foo

    </div> [:div#my-id.class1.class2 "foo"] Tuesday, June 11, 13
  58. © 2013 innoQ Deutschland GmbH middleware request response handler middleware

    routing ... JSON HTML Tuesday, June 11, 13
  59. © 2013 innoQ Deutschland GmbH middleware {} {} handler middleware

    routing ... JSON HTML servlet adapter javax.servlet.http. HttpServletRequest javax.servlet.http. HttpServletRespone Tuesday, June 11, 13
  60. © 2013 innoQ Deutschland GmbH Conclusion Tuesday, June 11, 13

  61. © 2013 innoQ Deutschland GmbH :-) ‣ Simple basic concepts

    ‣ Easy to use ‣ Little code (also in libraries) ‣ Helpful community ‣ Mature eco system Tuesday, June 11, 13
  62. Thank you! We'll take care of it. Personally. © 2012

    innoQ Deutschland GmbH Philipp Schirmacher philipp.schirmacher@innoq.com @pschirmacher Tuesday, June 11, 13
  63. © 2013 innoQ Deutschland GmbH Backup Tuesday, June 11, 13

  64. © 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