Upload
bdemchak
View
925
Download
1
Embed Size (px)
Citation preview
Web Programming in Clojure
Barry DemchakCSE294
November 12, 2010
Agenda
• Different REPLs– Eclipse with Counterclockwise– Leiningen
• Compojure Web Framework– Application structure– Framework execution model– High level walkthrough– Addons
• Alternate Frameworks
REPL with Eclipse
• http://www.assembla.com/wiki/show/clojure/Getting_Started_with_Eclipse_and_Counterclockwise
• Install Counterclockwise– Plugin for Eclipse– Create and run simple Clojure project
(firstClojureProject)– Run REPL in console window
• Install the labrepl project (and git/maven)– Good online tutorial
REPL with Leiningen (“lein”)
• First, install Leiningen – a build tool for Clojure– http://www.assembla.com/wiki/show/clojure/Ge
tting_Started_with_Leiningen– Installation downloads itself
• Use Lein to create a project– Create .clj project file– Use editor to add dependencies– Use Lein to satisfy dependencies– Use Lein to start a REPL
https://github.com/weavejester/compojure/wiki/Getting-Started
Agenda
• Different REPLs– Eclipse with Counterclockwise– Leiningen
• Compojure Web Framework– Application structure– Framework execution model– High level walkthrough– Addons
• Alternate Frameworks
Compojure ComponentsCompojure Web App
Ring
Clout Hiccup
Middleware
«uses»
«call»
«call»
Handler«call»
«uses»
Abstract HTTP as {request} and {response}
Enhance {request} and route to user-defined handler
Transform {request} into {response}
Compojure component
Application component
DSL for writing HTML
Compojure Execution Model
What is a “handler”?
• {request} is a map– :server-port 80– :server-name “127.0.0.1”– :remote-addr “127.0.0.1”– :uri “/”– :scheme :http– :headers {}– :request-method :get
• {response} is a map– :status 200
– :headers {:X-lang “Clojure” :X-Framework “Compojure”}
– :body “Hello world”
{request} handler {response}
http://groups.google.com/group/compojure/msg/9b9c01a737242b58?http://efreedom.com/Question/1-3488353/Big-Idea-Behind-Compojure-Routes#3490479
Preview: Simplifying handler construction is Compojure’s key value proposition
The “Ring”
http://www.slideshare.net/mmcgrana/ring-web-apps-in-idiomatic-clojure
• (ns example-app (:use compojure.server.jetty))
• (defn hello-world [request] {:status 200 :headers {}
:body "Hello World"}) • (run-server
{:port 8080} "/*"
(servlet hello-world))
A Simple Servlet Using Ring
http://groups.google.com/group/compojure/msg/9b9c01a737242b58?
Getting Started with Compojure
• https://github.com/weavejester/compojure/wiki/Getting-Started
• Use lien to create a project and dependencies
Agenda
• Different REPLs– Eclipse with Counterclockwise– Leiningen
• Compojure Web Framework– Application structure– Framework execution model– High level walkthrough– Addons
• Alternate Frameworks
A Simple Compojure Web Server
• (ns hello-www.core (:use compojure.core)
(:require [compojure.route :as route]))• (defroutes example
(GET "/" [] "<h1>Hello World Wide Web!</h1>") (route/not-found "Page not found"))
http://weavejester.github.com/compojure/docs/getting-started.html
Clojure Interlude – Useful Macros• (def hello-world (-> hello-world (with-header "X-Lang" "Clojure")
(with-header "X-Framework" "Compojure")))
• (with-header
(with-header
hello-world "X-Lang" "Clojure") "X-Framework" "Compojure")
• (decorate hello-world (with-header "X-Lang" "Clojure") (with-header "X-Framework" "Compojure"))
Compojure Middleware
• (defn with-header[handler header value] (fn [request] (let [response (handler request)] (assoc-in response
[:headers header] value))))
• (decorate hello-world (with-header "X-Lang" "Clojure") (with-header "X-Framework" "Compojure"))
handler & args middleware handler
http://groups.google.com/group/compojure/msg/9b9c01a737242b58?
Compojure Middleware (cont’d)
• Route Handlers return nil if criteria not met– (defn index-route [request]
(if (and (= (:request-method request) :get) (= (:uri request) "/")) {:status 200 :headers {} :body "The index page"))
– (def index-route (GET “/” “The index page”))
http://groups.google.com/group/compojure/msg/9b9c01a737242b58?
Route Components
Route
HTTPMethod
ResponseFunction
URIPattern
DestructuringForm
HTTP command to match
Pattern of URI to match
Extract attributes into local values
Generate response
Index Routes
• (def index-route (GET "/" "The index page"))
• … (GET "/product/:id" (str "You chose product: " (-> request :route-params :id)))
• … (GET #"/product/(\d+)" (str "You chose product: " ((:route-params request) 0)))
Method macro
(GET, PUT, POST …)
Variable capture
Regular
expression matching
http://groups.google.com/group/compojure/msg/9b9c01a737242b58?
Index Routes (cont’d)
• (def echo-typed-url-route (GET "*"
{:keys [scheme server-name server-port uri]}
(str (name scheme) "://" server-name ":“ server-port uri)))
• (defroutes main-routes (POST "/save" {form-params :form-params} (str form-params))
http://efreedom.com/Question/1-3488353/Big-Idea-Behind-Compojure-Routes#3490479
Destructuring
defroutes wraps wrap-params,
wrap-cookies around handler
Destructuring and Local Bindings
• Additional functions update namespace local vars– with-params (:params)– with-cookies (:cookies)– with-multipart– with-session (:session)– with-stacktrace
• Many more documented at http://v-182-163-94-96.ub-freebit.net:8080/docs/api
http://groups.google.com/group/compojure/msg/9b9c01a737242b58?
Response Values
• Base class - {:status 200, :headers {}}• Modification depends on class of modifier
– Integer sets status code– String adds to response body– ISeq, File, and InputStream set response body– URL opens stream and sets response body– Map merges into return value map– Fn produces response from request & response maps– IPersistentVector updates response map
http://groups.google.com/group/compojure/msg/9b9c01a737242b58?
Response Value Examples
• …(GET “/” “Index page”)• …(ANY “*” [404 “Page not found”])• …(GET “/image”
(File. “./public/image.png”))• …(GET “/new-product”
(if product-released? “Cool!” :next))• …(GET “/map-example” {:body “Hi there!”})
http://groups.google.com/group/compojure/msg/9b9c01a737242b58?
HTML Compojure (Hiccup)
• [:h1 {:id “title”} “Hello”] [:h1#id “title” “Hello”]
• [:div (list “Hello” “ Ingolf”)]
• [:div [:span “Hello”] [:span “ Ingolf”]]
{tag attribute-map content}
• <h1 id=“title”>Hello</h1>
• <div>Hello Ingolf</div>
• <div><span>Hello</span><span>Ingolf</span>
</div>
Clojure HTML
http://groups.google.com/group/compojure/msg/9b9c01a737242b58?
Agenda
• Different REPLs– Eclipse with Counterclockwise– Leiningen
• Compojure Web Framework– Application structure– Framework execution model– High level walkthrough– Addons
• Alternate Frameworks
Compojure Addons
• Sandbar– Session and flash as a global map– Authorization and authentication (form-based)– Forms and form validation
https://github.com/brentonashworth/sandbar
Other Web Frameworks• Enlive
– light weight, non-inference routing• Webjure
– light weight, provides routing and parsing on top of Java servlets, Clojure Page Templates
• Conjure– Rails-like framework for Clojure
• Moustache– a micro web framework/internal DSL to wire Ring handlers and
middlewares• Funkyweb
– ring based framework with route inferencehttps://github.com/cgrand/moustache
https://github.com/tatut/Webjurehttp://www.lshift.net/blog/2010/02/27/a-simple-web-application-in-clojure-using-ring-and-enlive
http://groups.google.com/group/clojure/browse_thread/thread/657adc458151e79a/5dfb6362542cf124
Enlive Example(ns sprout.core)
(defn router [req] (condp = (:uri req) "/error" {:status 404
:headers {"Content-Type" "text/html"} :body (str "Error")}
"/info" {:status 200 :headers {"Content-Type" "text/html"} :body (str "Ring on " (:server-name req)) }
{:status 200 :headers {"Content-Type" "text/html"} :body (str "Welcome")}))
(defn app [req] (router req)) http://www.lshift.net/blog/2010/02/27/a-simple-web-application-in-clojure-using-ring-and-enlive
Questions
• Why is Compojure named Compojure?• What are the requirements of the underlying Java-
based web server to support?– Scalability– Extensibility
• How would Compojure participate in web standards?– Web Services (non-Rest)– WS-*
• In the long run, does Compojure need Java?• Does Java need Compojure?
Other References• Clojure Web Development with Ring http://
mmcgrana.github.com/2010/03/clojure-web-development-ring.html• Compojure: Clojure Web Framework https://
github.com/blog/308-compojure-clojure-web-framework• How do you make a web application in Clojure? http://
stackoverflow.com/questions/167262/how-do-you-make-a-web-application-in-clojure• Introduction to the Compojure web Framework http://
groups.google.com/group/clojure/browse_frm/thread/448865254f9bd293?pli=1• mmcgrana’s ring at master https://github.com/mmcgrana/ring• weavejester‘s compojure at master https://github.com/weavejester/compojure• weavejester’s hiccup at master https://github.com/weavejester/hiccup• WEB DEVELOPMENT – Mature Clojure web frameworks http://
efreedom.com/Question/1-3551805/Mature-Clojure-Web-Frameworks• arbscht‘s clout at string-keys https://github.com/arbscht/clout/tree/string-keys• cgrand‘s enlive at master https://github.com/cgrand/enlive