Slide 1

Slide 1 text

We'll take care of it. Personally. Clojure Web Development Philipp Schirmacher | innoQ Tuesday, June 11, 13

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

© 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

Slide 4

Slide 4 text

© 2013 innoQ Deutschland GmbH Lisp?? Tuesday, June 11, 13

Slide 5

Slide 5 text

© 2013 innoQ Deutschland GmbH Lots of irritating silly parentheses Tuesday, June 11, 13

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

© 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

Slide 11

Slide 11 text

© 2013 innoQ Deutschland GmbH Functions Tuesday, June 11, 13

Slide 12

Slide 12 text

© 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

Slide 13

Slide 13 text

© 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

Slide 14

Slide 14 text

© 2013 innoQ Deutschland GmbH (defn activity [weather] (if (nice? weather) :surfing :playstation)) Tuesday, June 11, 13

Slide 15

Slide 15 text

© 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

Slide 16

Slide 16 text

© 2013 innoQ Deutschland GmbH Web Development? Tuesday, June 11, 13

Slide 17

Slide 17 text

© 2013 innoQ Deutschland GmbH app request response data function Tuesday, June 11, 13

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

© 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

Slide 20

Slide 20 text

© 2013 innoQ Deutschland GmbH (defn my-first-homepage [req] {:status 200 :headers {"Content-Type" "text/html"} :body (str "" "" "" "

Welcome to my Homepage

" (java.util.Date.) "")}) Tuesday, June 11, 13

Slide 21

Slide 21 text

© 2013 innoQ Deutschland GmbH static resources request response homepage Tuesday, June 11, 13

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

© 2013 innoQ Deutschland GmbH (defn decorate [webapp] (fn [req] (if (static-resource? req) (return-resource req) (webapp req)))) Tuesday, June 11, 13

Slide 24

Slide 24 text

© 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

Slide 25

Slide 25 text

© 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

Slide 26

Slide 26 text

© 2013 innoQ Deutschland GmbH (webapp {:uri "/pretty.css" :request-method :get :headers {}}) > {:status 200 :headers {} :body #} Tuesday, June 11, 13

Slide 27

Slide 27 text

© 2013 innoQ Deutschland GmbH wrap-resource request response my- rst-homepage wrap- le-info Tuesday, June 11, 13

Slide 28

Slide 28 text

© 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

Slide 29

Slide 29 text

© 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 #} Tuesday, June 11, 13

Slide 30

Slide 30 text

© 2013 innoQ Deutschland GmbH wrap-resource wrap- le wrap-params wrap-session wrap-flash wrap-etag wrap-basic-authentication Tuesday, June 11, 13

Slide 31

Slide 31 text

© 2013 innoQ Deutschland GmbH middleware request response handler middleware routing ... Tuesday, June 11, 13

Slide 32

Slide 32 text

© 2013 innoQ Deutschland GmbH Compojure Tuesday, June 11, 13

Slide 33

Slide 33 text

© 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

Slide 34

Slide 34 text

© 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

Slide 35

Slide 35 text

© 2013 innoQ Deutschland GmbH Digression: Macros Tuesday, June 11, 13

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

© 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

Slide 38

Slide 38 text

© 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

Slide 39

Slide 39 text

© 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

Slide 40

Slide 40 text

© 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

Slide 41

Slide 41 text

© 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

Slide 42

Slide 42 text

© 2013 innoQ Deutschland GmbH Back to Compojure... Tuesday, June 11, 13

Slide 43

Slide 43 text

© 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

Slide 44

Slide 44 text

© 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

Slide 45

Slide 45 text

© 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

Slide 46

Slide 46 text

© 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

Slide 47

Slide 47 text

© 2013 innoQ Deutschland GmbH middleware request response handler middleware routing ... JSON HTML Tuesday, June 11, 13

Slide 48

Slide 48 text

© 2013 innoQ Deutschland GmbH Hiccup Tuesday, June 11, 13

Slide 49

Slide 49 text

© 2013 innoQ Deutschland GmbH bar [:element] Tuesday, June 11, 13

Slide 50

Slide 50 text

© 2013 innoQ Deutschland GmbH bar [:element {:attribute "foo"}] Tuesday, June 11, 13

Slide 51

Slide 51 text

© 2013 innoQ Deutschland GmbH bar [:element {:attribute "foo"} [:nested]] Tuesday, June 11, 13

Slide 52

Slide 52 text

© 2013 innoQ Deutschland GmbH bar [:element {:attribute "foo"} [:nested "bar"]] Tuesday, June 11, 13

Slide 53

Slide 53 text

© 2013 innoQ Deutschland GmbH Foo

Bar

(def hiccup-example [:html [:head [:title "Foo"]] [:body [:p "Bar"]]]) (html hiccup-example) > "..." Tuesday, June 11, 13

Slide 54

Slide 54 text

© 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)) > "
Name
Paul
...
" Tuesday, June 11, 13

Slide 55

Slide 55 text

© 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

Slide 56

Slide 56 text

© 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

Slide 57

Slide 57 text

© 2013 innoQ Deutschland GmbH
foo
[:div#my-id.class1.class2 "foo"] Tuesday, June 11, 13

Slide 58

Slide 58 text

© 2013 innoQ Deutschland GmbH middleware request response handler middleware routing ... JSON HTML Tuesday, June 11, 13

Slide 59

Slide 59 text

© 2013 innoQ Deutschland GmbH middleware {} {} handler middleware routing ... JSON HTML servlet adapter javax.servlet.http. HttpServletRequest javax.servlet.http. HttpServletRespone Tuesday, June 11, 13

Slide 60

Slide 60 text

© 2013 innoQ Deutschland GmbH Conclusion Tuesday, June 11, 13

Slide 61

Slide 61 text

© 2013 innoQ Deutschland GmbH :-) ‣ Simple basic concepts ‣ Easy to use ‣ Little code (also in libraries) ‣ Helpful community ‣ Mature eco system Tuesday, June 11, 13

Slide 62

Slide 62 text

Thank you! We'll take care of it. Personally. © 2012 innoQ Deutschland GmbH Philipp Schirmacher [email protected] @pschirmacher Tuesday, June 11, 13

Slide 63

Slide 63 text

© 2013 innoQ Deutschland GmbH Backup Tuesday, June 11, 13

Slide 64

Slide 64 text

© 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