Thanks to visit codestin.com
Credit goes to www.slideshare.net

Web Programming in Clojure
Barry Demchak
CSE294
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/Gettin
g_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/Get
ting_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 Components
Compojure 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/w
iki/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
HTTP
Method
Response
Function
URI
Pattern
Destructuring
Form
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)))
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 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 inference
https://github.com/cgrand/moustache
https://github.com/tatut/Webjure
http://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

Web programming in clojure

  • 1.
    Web Programming inClojure Barry Demchak CSE294 November 12, 2010
  • 2.
    Agenda • Different REPLs –Eclipse with Counterclockwise – Leiningen • Compojure Web Framework – Application structure – Framework execution model – High level walkthrough – Addons • Alternate Frameworks
  • 3.
    REPL with Eclipse •http://www.assembla.com/wiki/show/clojure/Gettin g_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
  • 4.
    REPL with Leiningen(“lein”) • First, install Leiningen – a build tool for Clojure – http://www.assembla.com/wiki/show/clojure/Get ting_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
  • 5.
    Agenda • Different REPLs –Eclipse with Counterclockwise – Leiningen • Compojure Web Framework – Application structure – Framework execution model – High level walkthrough – Addons • Alternate Frameworks
  • 6.
    Compojure Components Compojure WebApp 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
  • 7.
    Compojure Execution Model Whatis 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
  • 8.
  • 9.
    • (ns example-app (:usecompojure.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?
  • 10.
    Getting Started withCompojure • https://github.com/weavejester/compojure/w iki/Getting-Started • Use lien to create a project and dependencies
  • 11.
    Agenda • Different REPLs –Eclipse with Counterclockwise – Leiningen • Compojure Web Framework – Application structure – Framework execution model – High level walkthrough – Addons • Alternate Frameworks
  • 12.
    A Simple CompojureWeb 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
  • 13.
    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"))
  • 14.
    Compojure Middleware • (defnwith-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?
  • 15.
    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?
  • 16.
    Route Components Route HTTP Method Response Function URI Pattern Destructuring Form HTTP command tomatch Pattern of URI to match Extract attributes into local values Generate response
  • 17.
    Index Routes • (defindex-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))) http://groups.google.com/group/compojure/msg/9b9c01a737242b58?
  • 18.
    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
  • 19.
    Destructuring and LocalBindings • 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?
  • 20.
    Response Values • Baseclass - {: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?
  • 21.
    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?
  • 22.
    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?
  • 23.
    Agenda • Different REPLs –Eclipse with Counterclockwise – Leiningen • Compojure Web Framework – Application structure – Framework execution model – High level walkthrough – Addons • Alternate Frameworks
  • 24.
    Compojure Addons • Sandbar –Session and flash as a global map – Authorization and authentication (form-based) – Forms and form validation https://github.com/brentonashworth/sandbar
  • 25.
    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 inference https://github.com/cgrand/moustache https://github.com/tatut/Webjure http://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
  • 26.
    Enlive Example (ns sprout.core) (defnrouter [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
  • 27.
    Questions • Why isCompojure 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?
  • 28.
    Other References • ClojureWeb 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

Editor's Notes

  • #4 Show these
  • #5 Show creating a project from https://github.com/weavejester/compojure/wiki/Getting-Started
  • #10 It does not run, but it’s useful to talk about run-server and middleware
  • #11 Show this web page
  • #13 Establish environment: C:\users\barry demchak\workspace\hello-www Start lein: lein repl Start web server by typing: (use 'ring.adapter.jetty) (use 'hello-www.core) (run-jetty example {:port 8080}) View result at http://localhost:8080
  • #14 Show http://clojure.github.com/clojure/clojure.core-api.html#clojure.core as an example of finding this out Show this, too: http://v-182-163-94-96.ub-freebit.net:8080/docs/api
  • #15 The “defn” defines a function “with-header” that accepts three parameters: “handler, header, and value” The function returns a new function that accepts a “request” parameter. It is defined to assign a “response” variable the result of calling handler(request) “assoc-in” adds headers and values to the “response” It’s possible to add other decorator functions, including those that change the response … this is the essence of a web service
  • #16 Next slide … look at 3.1.1 … the method Macro
  • #20 Note that *params*, *cookies*, etc are namespace global vars