Jim Crossley
                                        jcrossley@redhat.com
       Creative  Commons  BY-­SA  3.0




Monday, March 19, 2012
Agenda

                    •    Who,  what,  WHY?
                    •    A  fake,  real-­life  application
                    •    How?
                    •    API  deep-­dive
                    •    Clustering,  etc




Monday, March 19, 2012
Who?

                    • Jim  Crossley  -­  @jcrossley3
                    • Toby  Crawley  -­  @tcrawley


                    • Bob  McWhirter  -­  Director  of  Polyglot
                    • JBoss  by  Red  Hat



Monday, March 19, 2012
What?

                    •    An  app  server  for  Clojure
                    •    Inspired  by  TorqueBox
                    •    Powered  by  JBoss  AS7
                    •    Started  in  September  2011




Monday, March 19, 2012
App  Server?


                    • Multiple  apps  running  in  same  JVM
                    • Isolation  via  classloaders
                    • Shared  common  services




Monday, March 19, 2012
Inspired  by  TorqueBox

                    • Make  Ring,  not  War
                    • Clojure  interfaces  to  JBoss  
                      middleware
                    • No  XML
                    • Adapt  AS7  to  the  Clojure  
                      development  common  practices



Monday, March 19, 2012
AS7  is  teh  awesome!
                    •    Tomcat  for  web
                    •    HornetQ  for  messaging
                    •    Infinispan  for  caching
                    •    Quartz  for  scheduling
                    •    Distributed  Transactions  (XA)
                    •    Clustering
                    •    Management/Monitoring  


Monday, March 19, 2012
Certified,  fwiw




                         Java  EE  6  Full  Profile

Monday, March 19, 2012
Why?
                    • Reduce  incidental  complexity
                    • Simplify  deployment  of  non-­trivial  
                      applications
                    • Simplify  clustering  to  achieve  high-­
                      availability
                    • Encapsulate  JBoss  services
                    • Exploit  the  JVM



Monday, March 19, 2012
Polyglot

                    • Leverage  the  best  tool  on  a  single  
                      platform,  regardless  of  language
                    • “ruby  in  the  front,  java  in  the  middle,  
                      clojure  in  the  rear”
                    • Red  Hat  is  committed  to  it




Monday, March 19, 2012
Maybe  a  fit?

                    • If  you’re  already  using  Jetty,  
                      Memcached,  RabbitMQ,  and/or  Cron
                    • If  you  have  a  polyglot  organization,  
                      especially  Ruby  and  Java
                    • If  you  must  integrate  with  legacy  
                      Java  EE



Monday, March 19, 2012
Let’s  Get  Real
                         CRUD  can  only  take  you  so  far




Monday, March 19, 2012
Apps  often  require...

                    • More  than  one  web  interface,  e.g.  
                      administration
                    • Background  processing
                    • Periodic  maintenance
                    • Dynamic  data  sources,  e.g.  REST
                    • Services



Monday, March 19, 2012
But...


                    We’d  still  like  to  treat  the  
                    integration  of  those  components  
                    as  a  single,  versioned  application.




Monday, March 19, 2012
Consider...

                    • A  tweet-­analysis  app
                    • Filters  the  Twitter  streaming  API  for  
                      brand  keywords
                    • Scrapes  URL’s  from  the  tweets
                    • Stores  weighted  results  of  sentiment  
                      analysis



Monday, March 19, 2012
Possible  Components...

                    •    A  web  app  for  displaying  impressions
                    •    An  admin  app  for  defining  users
                    •    The  Twitter  streaming  client
                    •    The  URL  scraper
                    •    A  housekeeper  to  purge  old  data




Monday, March 19, 2012
The  Web  Apps


                  ;;;;  Mount  the  ring  handlers
                  (web/start  “/”  brandy.web/app)
                  (web/start  “/admin”  brandy.web/admin)




Monday, March 19, 2012
The  Message  Queue

                  ;;;;  Where  scrapers  pick  up  their  work
                  (msg/start  “/queue/tweets”)

                  ;;;;  The  scrapers
                  (msg/listen  “/queue/tweets”  
                                          brandy.msg/scrape)




Monday, March 19, 2012
The  Twitter  Service


                  ;;;;  The  work  producer
                  (daemon/start  “streamer”  
                                              brandy.stream/start  
                                              brandy.stream/stop)




Monday, March 19, 2012
The  Recurring  Job


                  ;;;;  The  housekeeper
                  (job/schedule  “housekeeper”  
                                              “0  0  0  *  *  ?”
                                              brandy.job/purge)




Monday, March 19, 2012
immutant.clj
                  ;;  The  ring  handlers
                  (web/start  “/”            brandy.web/app)
                  (web/start  “/admin”  brandy.web/admin)

                  ;;  Where  scrapers  pick  up  their  work
                  (msg/start  “/queue/tweets”)

                  ;;  The  scrapers
                  (msg/listen  “/queue/tweets”  brandy.msg/scrape)

                  ;;  The  work  producer
                  (daemon/start  “streamer”  brandy.stream/start  
                                                                    brandy.stream/stop)
                  ;;  The  housekeeper
                  (job/schedule  “housekeeper”  “0  0  0  *  *  ?”
                                                                          brandy.job/purge)



Monday, March 19, 2012
immutant.clj
                  ;;  The  ring  handlers
                  (web/start  “/”            brandy.web/app)
                  (web/start  “/admin”  brandy.web/admin)

                  ;;  Where  scrapers  pick  up  their  work
                  (msg/start  “/queue/tweets”)

                  ;;  The  scrapers
                  (msg/listen  “/queue/tweets”  brandy.msg/scrape)

                  ;;  The  work  producer
                  (daemon/start  “streamer”  brandy.stream/start  
                                                                    brandy.stream/stop)
                  ;;  The  housekeeper
                  (job/schedule  “housekeeper”  “0  0  0  *  *  ?”
                                                                          brandy.job/purge)



Monday, March 19, 2012
immutant.clj
                  ;;  The  ring  handlers
                  (web/start  “/”            brandy.web/app)
                  (web/start  “/admin”  brandy.web/admin)

                  ;;  Where  scrapers  pick  up  their  work
                  (msg/start  “/queue/tweets”)

                  ;;  The  scrapers
                  (msg/listen  “/queue/tweets”  brandy.msg/scrape)

                  ;;  The  work  producer
                  (daemon/start  “streamer”  brandy.stream/start  
                                                                    brandy.stream/stop)
                  ;;  The  housekeeper
                  (job/schedule  “housekeeper”  “0  0  0  *  *  ?”
                                                                          brandy.job/purge)



Monday, March 19, 2012
Immutant
                           how?




Monday, March 19, 2012
Leiningen  Plugin




                  $  lein  plugin  install  lein-­immutant  0.6.0




Monday, March 19, 2012
Install



                  $  lein  immutant  install  [version]




Monday, March 19, 2012
Install


                    By  default,  the  plugin  installs  
                    Immutant  beneath  

                          ~/.lein/immutant/



Monday, March 19, 2012
Run



                  $  lein  immutant  run




Monday, March 19, 2012
Deploy

                  $  lein  new  myapp
                  $  cd  myapp

                  $  lein  immutant  init
                  $  $EDITOR  immutant.clj

                  $  lein  immutant  deploy




Monday, March 19, 2012
Deploy

                    A  “deployment  descriptor”  is  a  
                    glorified  symlink  written  to  
                    jboss/standalone/deployments


                    Its  contents:
                    {:root  "/the/path/to/your/app"}



Monday, March 19, 2012
Deploy

                    Each  app  gets  a  dedicated  
                    Clojure  runtime  and  classpath  
                    containing  resolved  
                    dependencies,  src,  lib,  and  
                    resources.


Monday, March 19, 2012
project.clj

                  (defproject  myapp  "1.2.3"
                      ...

                      :immutant  {:init  myapp.core/initialize
                                            :resolve-­dependencies  true
                                            :context-­path  "/"
                                            :swank-­port  4111
                                            :nrepl-­port  4112})




Monday, March 19, 2012
Overlay


                  $  lein  immutant  overlay  torquebox

                  $  export  TORQUEBOX_HOME=$IMMUTANT_HOME




Monday, March 19, 2012
The  API
                         immutant  namespaces




Monday, March 19, 2012
The  API
                    • Dynamic  by  design
                      • No  static  xml  files  or  annotations
                    • Modules
                      • Web
                      • Messaging
                      • Caching  
                      • Scheduling
                      • Daemons


Monday, March 19, 2012
immutant.web
                              ring




Monday, March 19, 2012
Web

                    • Supports  any  Ring-­based  handler
                    • Ring  middleware  to  expose  the  
                      Servlet  session
                    • Multiple  web  apps  may  share  the  
                      same  lifecycle  via  “subcontexts”




Monday, March 19, 2012
Web

                  (require  ‘[immutant.web  :as  web])

                  (defn  my-­handler  [request]
                      {:status  200
                        :headers  {"Content-­Type"  "text/html"}
                        :body  "Hello  from  Immutant!"})

                  (web/start  "/hi"  my-­handler)




Monday, March 19, 2012
Context  paths
                  project.clj

                  (defproject  myapp  "1.2.3"  ...)

                  immutant.clj

                  (web/start  "/"  main)
                  ;;;;  http://localhost:8080/myapp/

                  (web/start  "/admin"  admin)
                  ;;;;  http://localhost:8080/myapp/admin




Monday, March 19, 2012
Context  paths
                  project.clj

                  (defproject  myapp  "1.2.3”
                      :immutant  {:context-­path  "/"})

                  immutant.clj

                  (web/start  "/"  main)
                  ;;;;  http://localhost:8080/

                  (web/start  "/admin"  admin)
                  ;;;;  http://localhost:8080/admin



Monday, March 19, 2012
Session  Replication

                  (require  ‘[immutant.web  :as  web]
                                    ‘[immutant.web.session  :as  iws])

                  (web/start  "/"
                      (ring-­session/wrap-­session
                          handler
                          {:store  (iws/servlet-­store)}))




Monday, March 19, 2012
immutant.messaging
                                hornetq




Monday, March 19, 2012
Messaging
               publish-­subscribe




               point-­to-­point




Monday, March 19, 2012
Messaging


                  (require  ‘[immutant.messaging  :as  msg])

                  (msg/start  "/queue/work")
                  (msg/start  "/topic/news")




Monday, March 19, 2012
Producers


                  ;;;;  Content  may  be  any  serializable
                  ;;;;  data  structure

                  (msg/publish  “/queue/work”  anything)




Monday, March 19, 2012
Producers


                  ;;;;  May  be  as  complex  as  necessary

                  (msg/publish  "/queue/work"  
                      {:a  "b"  :c  [1  2  3  {:foo  42}]})




Monday, March 19, 2012
Producers

                  ;;;;  Support  priority  and  time-­to-­live

                  (msg/publish  “/queue/work”  
                                            a-­message  
                                            :priority  :high
                                            :ttl  1000)




Monday, March 19, 2012
Producers

                  ;;;;  Three  message  encodings:
                  ;;;;  :clojure  :json  :text

                  (msg/publish  "/queue/work"  
                      {:a  "b"  :c  [1  2  3  {:foo  42}]}
                      :encoding  :json)




Monday, March 19, 2012
Messaging

                    With  TorqueBox,  messages  
                    comprised  of  standard  collections  
                    and  types  are  transparently  
                    interoperable  between  Clojure  
                    and  Ruby  in  either  direction.


Monday, March 19, 2012
Consumers


                  ;;;;  Block  until  message  arrives

                  (let  [task  (msg/receive  "/queue/work")]
                      (perform  task))




Monday, March 19, 2012
Consumers


                  ;;;;  Create  a  lazy  sequence  of  messages

                  (take  4  (msg/message-­seq  “/queue/foo”))




Monday, March 19, 2012
Consumers

                  (defn  upper-­caser  [s]
                      (msg/publish  "/topic/upper"
                                                (.toUpperCase  s)))

                  ;;;;  Register  a  listener
                  (msg/listen  "/queue/lower"  upper-­caser)




Monday, March 19, 2012
Messaging



                    Automatic  retries,  failover  and  
                    load-­balancing  when  clustered.




Monday, March 19, 2012
immutant.cache
                             infinispan




Monday, March 19, 2012
Distributed  Cache

                    • Backed  by  Infinispan  data  grid
                    • Implements  core  Clojure  interfaces
                    •core.cache/CacheProtocol
                    • core.memoize  store




Monday, March 19, 2012
Infinispan

                    •    Eviction:  FIFO,  LRU
                    •    Expiration:  time-­to-­live,  idle  time
                    •    Persistence:  write-­through/behind
                    •    Transactional:  JTA/XA
                    •    MVCC-­based  concurrency
                    •    Flexible  clustering



Monday, March 19, 2012
Cache  Modes

                    • :local  -­  non-­clustered
                    • Clustered
                      • :invalidated  -­  no  data  shared
                      • :replicated  -­  all  data  shared
                      • :distributed  -­  linear  scalability




Monday, March 19, 2012
:invalidated




Monday, March 19, 2012
:replicated




Monday, March 19, 2012
:distributed




Monday, March 19, 2012
immutant.cache

                    • All  caches  have  a  name  and  a  mode  
                      (:local,  :invalidated,  :replicated,  
                      :distributed)
                    • Like-­named  Immutant  caches  are  
                      backed  by  the  same  Infinispan  cache




Monday, March 19, 2012
immutant.cache


                  (require  ‘[immutant.cache  :as  ic])

                  (def  a  (ic/cache  “foo”  :replicated))
                  (def  b  (ic/cache  “bar”))
                  (def  c  (ic/cache  “foo”))




Monday, March 19, 2012
immutant.cache

                  (def  c  (ic/cache  “foo”))
                  (assoc  c  :a  1)
                  (merge  c  {:b  2  :c  3})
                  (dissoc  c  :c)

                  c  =>  {:a  1,  :b  2}




Monday, March 19, 2012
Memoization

                  (require  ‘[immutant.cache  :as  ic])

                  (def  memoized-­fn  (ic/memo  slow-­fn  “foo”))
                  (memoized-­fn  1  2  3)
                  (def  c  (ic/cache  “foo”))

                  c  =>  {[1  2  3]  42}




Monday, March 19, 2012
Explicit  writes
                  (require  ‘[immutant.cache  :as  ic])

                  (def  opts  {:ttl  2  :idle  1  :units  :days})
                  (def  c  (ic/cache  “foo”))

                  (ic/put  c  key  value  opts)
                  (ic/put-­if-­absent  c  key  value  opts)
                  (ic/put-­if-­present  c  key  value  opts)
                  (ic/put-­if-­replace  c  key  old  new  opts)
                  (ic/delete  c  key)




Monday, March 19, 2012
immutant.jobs
                              quartz




Monday, March 19, 2012
Scheduling

                  (require  ‘[immutant.jobs  :as  job])

                  ;;;;  Once  a  month
                  (job/schedule  "newsletter"
                                              "0  0  0  1  *  ?"
                                              news/monthly
                                              :singleton  true)




Monday, March 19, 2012
Scheduling
                  “Fire  every  half  hour  from  10am  until  1pm  on  
                          the  third  Friday  of  each  month”

                         0   */30 10-13      ?      *      FRI#3

                Seconds Minutes     Hours   DOM    Month   DOW     Year

                                                            1-7
                                                   1-12            1970-
                                            1-31           SUN-
                    0-59     0-59   0-23           JAN-            2099
                                            ?LW            SAT
                                                   DEC             empty
                                                           ?L#



Monday, March 19, 2012
Scheduling

                  (require  ‘[immutant.jobs  :as  job])

                  (job/at  “name”  “3m”  
                      #(println  “I  fire  after  3  minutes”))

                  (job/every  “name”  “1d”
                      #(println  “I  fire  once  a  day”))




Monday, March 19, 2012
immutant.daemons
                            long-­running  services




Monday, March 19, 2012
Daemons


                  (require  ‘[immutant.daemons  :as  daemon])

                  (daemon/start  "name"  start-­fn  stop-­fn)




Monday, March 19, 2012
Daemons
                  (def  response  (atom  nil))

                  (defn  start  []
                      (reset!  response
                          (twitter-­statuses-­filter  
                              (terms)
                              url-­scraper)))

                  (defn  stop  []  
                      ((:cancel  (meta  @response))))

                  (daemon/start  "tweets"  start  stop  
                                              :singleton  true)



Monday, March 19, 2012
Clustering
                         simple  horizontal  scaling




Monday, March 19, 2012
Clustering



                  $  lein  immutant  run  -­-­clustered




Monday, March 19, 2012
Clustering

                    • Session  replication
                    • Robust,  load-­balanced  message  
                      distribution
                    • HA  Singleton
                    • HA  Jobs
                    • Infinispan



Monday, March 19, 2012
mod_cluster

                    • An  Apache  module  aware  of  JBoss
                    • Reverse  proxy  via  AJP  or  HTTP[S]
                    • Uses  load  statistics  and  deployment  
                      availability  for  intelligent  routing
                    • Optional  session  affinity
                    • Failover



Monday, March 19, 2012
mod_cluster




Monday, March 19, 2012
Coming  soon

                    •    Distributed  Transactions  (XA)
                    •    OpenShift  integration
                    •    Websockets
                    •    Better  remote  support
                    •    Domain  Mode  (cluster  management)




Monday, March 19, 2012
http://immutant.org
                              #immutant  
                            @immutants




Monday, March 19, 2012
Introducing Immutant

Introducing Immutant

  • 1.
    Jim Crossley jcrossley@redhat.com Creative  Commons  BY-­SA  3.0 Monday, March 19, 2012
  • 2.
    Agenda • Who,  what,  WHY? • A  fake,  real-­life  application • How? • API  deep-­dive • Clustering,  etc Monday, March 19, 2012
  • 3.
    Who? • Jim  Crossley  -­  @jcrossley3 • Toby  Crawley  -­  @tcrawley • Bob  McWhirter  -­  Director  of  Polyglot • JBoss  by  Red  Hat Monday, March 19, 2012
  • 4.
    What? • An  app  server  for  Clojure • Inspired  by  TorqueBox • Powered  by  JBoss  AS7 • Started  in  September  2011 Monday, March 19, 2012
  • 5.
    App  Server? • Multiple  apps  running  in  same  JVM • Isolation  via  classloaders • Shared  common  services Monday, March 19, 2012
  • 6.
    Inspired  by  TorqueBox • Make  Ring,  not  War • Clojure  interfaces  to  JBoss   middleware • No  XML • Adapt  AS7  to  the  Clojure   development  common  practices Monday, March 19, 2012
  • 7.
    AS7  is  teh awesome! • Tomcat  for  web • HornetQ  for  messaging • Infinispan  for  caching • Quartz  for  scheduling • Distributed  Transactions  (XA) • Clustering • Management/Monitoring   Monday, March 19, 2012
  • 8.
    Certified,  fwiw Java  EE  6  Full  Profile Monday, March 19, 2012
  • 9.
    Why? • Reduce  incidental  complexity • Simplify  deployment  of  non-­trivial   applications • Simplify  clustering  to  achieve  high-­ availability • Encapsulate  JBoss  services • Exploit  the  JVM Monday, March 19, 2012
  • 10.
    Polyglot • Leverage  the  best  tool  on  a  single   platform,  regardless  of  language • “ruby  in  the  front,  java  in  the  middle,   clojure  in  the  rear” • Red  Hat  is  committed  to  it Monday, March 19, 2012
  • 11.
    Maybe  a  fit? • If  you’re  already  using  Jetty,   Memcached,  RabbitMQ,  and/or  Cron • If  you  have  a  polyglot  organization,   especially  Ruby  and  Java • If  you  must  integrate  with  legacy   Java  EE Monday, March 19, 2012
  • 12.
    Let’s  Get  Real CRUD  can  only  take  you  so  far Monday, March 19, 2012
  • 13.
    Apps  often  require... • More  than  one  web  interface,  e.g.   administration • Background  processing • Periodic  maintenance • Dynamic  data  sources,  e.g.  REST • Services Monday, March 19, 2012
  • 14.
    But... We’d  still  like  to  treat  the   integration  of  those  components   as  a  single,  versioned  application. Monday, March 19, 2012
  • 15.
    Consider... • A  tweet-­analysis  app • Filters  the  Twitter  streaming  API  for   brand  keywords • Scrapes  URL’s  from  the  tweets • Stores  weighted  results  of  sentiment   analysis Monday, March 19, 2012
  • 16.
    Possible  Components... • A  web  app  for  displaying  impressions • An  admin  app  for  defining  users • The  Twitter  streaming  client • The  URL  scraper • A  housekeeper  to  purge  old  data Monday, March 19, 2012
  • 17.
    The  Web  Apps ;;;;  Mount  the  ring  handlers (web/start  “/”  brandy.web/app) (web/start  “/admin”  brandy.web/admin) Monday, March 19, 2012
  • 18.
    The  Message  Queue ;;;;  Where  scrapers  pick  up  their  work (msg/start  “/queue/tweets”) ;;;;  The  scrapers (msg/listen  “/queue/tweets”                          brandy.msg/scrape) Monday, March 19, 2012
  • 19.
    The  Twitter  Service ;;;;  The  work  producer (daemon/start  “streamer”                              brandy.stream/start                              brandy.stream/stop) Monday, March 19, 2012
  • 20.
    The  Recurring  Job ;;;;  The  housekeeper (job/schedule  “housekeeper”                              “0  0  0  *  *  ?”                            brandy.job/purge) Monday, March 19, 2012
  • 21.
    immutant.clj ;;  The  ring  handlers (web/start  “/”            brandy.web/app) (web/start  “/admin”  brandy.web/admin) ;;  Where  scrapers  pick  up  their  work (msg/start  “/queue/tweets”) ;;  The  scrapers (msg/listen  “/queue/tweets”  brandy.msg/scrape) ;;  The  work  producer (daemon/start  “streamer”  brandy.stream/start                                                    brandy.stream/stop) ;;  The  housekeeper (job/schedule  “housekeeper”  “0  0  0  *  *  ?”                                                        brandy.job/purge) Monday, March 19, 2012
  • 22.
    immutant.clj ;;  The  ring  handlers (web/start  “/”            brandy.web/app) (web/start  “/admin”  brandy.web/admin) ;;  Where  scrapers  pick  up  their  work (msg/start  “/queue/tweets”) ;;  The  scrapers (msg/listen  “/queue/tweets”  brandy.msg/scrape) ;;  The  work  producer (daemon/start  “streamer”  brandy.stream/start                                                    brandy.stream/stop) ;;  The  housekeeper (job/schedule  “housekeeper”  “0  0  0  *  *  ?”                                                        brandy.job/purge) Monday, March 19, 2012
  • 23.
    immutant.clj ;;  The  ring  handlers (web/start  “/”            brandy.web/app) (web/start  “/admin”  brandy.web/admin) ;;  Where  scrapers  pick  up  their  work (msg/start  “/queue/tweets”) ;;  The  scrapers (msg/listen  “/queue/tweets”  brandy.msg/scrape) ;;  The  work  producer (daemon/start  “streamer”  brandy.stream/start                                                    brandy.stream/stop) ;;  The  housekeeper (job/schedule  “housekeeper”  “0  0  0  *  *  ?”                                                        brandy.job/purge) Monday, March 19, 2012
  • 24.
    Immutant how? Monday, March 19, 2012
  • 25.
    Leiningen  Plugin $  lein  plugin  install  lein-­immutant  0.6.0 Monday, March 19, 2012
  • 26.
    Install $  lein  immutant  install  [version] Monday, March 19, 2012
  • 27.
    Install By  default,  the  plugin  installs   Immutant  beneath        ~/.lein/immutant/ Monday, March 19, 2012
  • 28.
    Run $  lein  immutant  run Monday, March 19, 2012
  • 29.
    Deploy $  lein  new  myapp $  cd  myapp $  lein  immutant  init $  $EDITOR  immutant.clj $  lein  immutant  deploy Monday, March 19, 2012
  • 30.
    Deploy A  “deployment  descriptor”  is  a   glorified  symlink  written  to   jboss/standalone/deployments Its  contents: {:root  "/the/path/to/your/app"} Monday, March 19, 2012
  • 31.
    Deploy Each  app  gets  a  dedicated   Clojure  runtime  and  classpath   containing  resolved   dependencies,  src,  lib,  and   resources. Monday, March 19, 2012
  • 32.
    project.clj (defproject  myapp  "1.2.3"    ...    :immutant  {:init  myapp.core/initialize                          :resolve-­dependencies  true                          :context-­path  "/"                          :swank-­port  4111                          :nrepl-­port  4112}) Monday, March 19, 2012
  • 33.
    Overlay $  lein  immutant  overlay  torquebox $  export  TORQUEBOX_HOME=$IMMUTANT_HOME Monday, March 19, 2012
  • 34.
    The  API immutant  namespaces Monday, March 19, 2012
  • 35.
    The  API • Dynamic  by  design • No  static  xml  files  or  annotations • Modules • Web • Messaging • Caching   • Scheduling • Daemons Monday, March 19, 2012
  • 36.
    immutant.web ring Monday, March 19, 2012
  • 37.
    Web • Supports  any  Ring-­based  handler • Ring  middleware  to  expose  the   Servlet  session • Multiple  web  apps  may  share  the   same  lifecycle  via  “subcontexts” Monday, March 19, 2012
  • 38.
    Web (require  ‘[immutant.web  :as  web]) (defn  my-­handler  [request]    {:status  200      :headers  {"Content-­Type"  "text/html"}      :body  "Hello  from  Immutant!"}) (web/start  "/hi"  my-­handler) Monday, March 19, 2012
  • 39.
    Context  paths project.clj (defproject  myapp  "1.2.3"  ...) immutant.clj (web/start  "/"  main) ;;;;  http://localhost:8080/myapp/ (web/start  "/admin"  admin) ;;;;  http://localhost:8080/myapp/admin Monday, March 19, 2012
  • 40.
    Context  paths project.clj (defproject  myapp  "1.2.3”    :immutant  {:context-­path  "/"}) immutant.clj (web/start  "/"  main) ;;;;  http://localhost:8080/ (web/start  "/admin"  admin) ;;;;  http://localhost:8080/admin Monday, March 19, 2012
  • 41.
    Session  Replication (require  ‘[immutant.web  :as  web]                  ‘[immutant.web.session  :as  iws]) (web/start  "/"    (ring-­session/wrap-­session        handler        {:store  (iws/servlet-­store)})) Monday, March 19, 2012
  • 42.
    immutant.messaging hornetq Monday, March 19, 2012
  • 43.
    Messaging publish-­subscribe point-­to-­point Monday, March 19, 2012
  • 44.
    Messaging (require  ‘[immutant.messaging  :as  msg]) (msg/start  "/queue/work") (msg/start  "/topic/news") Monday, March 19, 2012
  • 45.
    Producers ;;;;  Content  may  be  any  serializable ;;;;  data  structure (msg/publish  “/queue/work”  anything) Monday, March 19, 2012
  • 46.
    Producers ;;;;  May  be  as  complex  as  necessary (msg/publish  "/queue/work"      {:a  "b"  :c  [1  2  3  {:foo  42}]}) Monday, March 19, 2012
  • 47.
    Producers ;;;;  Support  priority  and  time-­to-­live (msg/publish  “/queue/work”                            a-­message                            :priority  :high                          :ttl  1000) Monday, March 19, 2012
  • 48.
    Producers ;;;;  Three  message  encodings: ;;;;  :clojure  :json  :text (msg/publish  "/queue/work"      {:a  "b"  :c  [1  2  3  {:foo  42}]}    :encoding  :json) Monday, March 19, 2012
  • 49.
    Messaging With  TorqueBox,  messages   comprised  of  standard  collections   and  types  are  transparently   interoperable  between  Clojure   and  Ruby  in  either  direction. Monday, March 19, 2012
  • 50.
    Consumers ;;;;  Block  until  message  arrives (let  [task  (msg/receive  "/queue/work")]    (perform  task)) Monday, March 19, 2012
  • 51.
    Consumers ;;;;  Create  a  lazy  sequence  of  messages (take  4  (msg/message-­seq  “/queue/foo”)) Monday, March 19, 2012
  • 52.
    Consumers (defn  upper-­caser  [s]    (msg/publish  "/topic/upper"                              (.toUpperCase  s))) ;;;;  Register  a  listener (msg/listen  "/queue/lower"  upper-­caser) Monday, March 19, 2012
  • 53.
    Messaging Automatic  retries,  failover  and   load-­balancing  when  clustered. Monday, March 19, 2012
  • 54.
    immutant.cache infinispan Monday, March 19, 2012
  • 55.
    Distributed  Cache • Backed  by  Infinispan  data  grid • Implements  core  Clojure  interfaces •core.cache/CacheProtocol • core.memoize  store Monday, March 19, 2012
  • 56.
    Infinispan • Eviction:  FIFO,  LRU • Expiration:  time-­to-­live,  idle  time • Persistence:  write-­through/behind • Transactional:  JTA/XA • MVCC-­based  concurrency • Flexible  clustering Monday, March 19, 2012
  • 57.
    Cache  Modes • :local  -­  non-­clustered • Clustered • :invalidated  -­  no  data  shared • :replicated  -­  all  data  shared • :distributed  -­  linear  scalability Monday, March 19, 2012
  • 58.
  • 59.
  • 60.
  • 61.
    immutant.cache • All  caches  have  a  name  and  a  mode   (:local,  :invalidated,  :replicated,   :distributed) • Like-­named  Immutant  caches  are   backed  by  the  same  Infinispan  cache Monday, March 19, 2012
  • 62.
    immutant.cache (require  ‘[immutant.cache  :as  ic]) (def  a  (ic/cache  “foo”  :replicated)) (def  b  (ic/cache  “bar”)) (def  c  (ic/cache  “foo”)) Monday, March 19, 2012
  • 63.
    immutant.cache (def  c  (ic/cache  “foo”)) (assoc  c  :a  1) (merge  c  {:b  2  :c  3}) (dissoc  c  :c) c  =>  {:a  1,  :b  2} Monday, March 19, 2012
  • 64.
    Memoization (require  ‘[immutant.cache  :as  ic]) (def  memoized-­fn  (ic/memo  slow-­fn  “foo”)) (memoized-­fn  1  2  3) (def  c  (ic/cache  “foo”)) c  =>  {[1  2  3]  42} Monday, March 19, 2012
  • 65.
    Explicit  writes (require  ‘[immutant.cache  :as  ic]) (def  opts  {:ttl  2  :idle  1  :units  :days}) (def  c  (ic/cache  “foo”)) (ic/put  c  key  value  opts) (ic/put-­if-­absent  c  key  value  opts) (ic/put-­if-­present  c  key  value  opts) (ic/put-­if-­replace  c  key  old  new  opts) (ic/delete  c  key) Monday, March 19, 2012
  • 66.
    immutant.jobs quartz Monday, March 19, 2012
  • 67.
    Scheduling (require  ‘[immutant.jobs  :as  job]) ;;;;  Once  a  month (job/schedule  "newsletter"                            "0  0  0  1  *  ?"                            news/monthly                            :singleton  true) Monday, March 19, 2012
  • 68.
    Scheduling “Fire  every  half  hour  from  10am  until  1pm  on   the  third  Friday  of  each  month” 0 */30 10-13 ? * FRI#3 Seconds Minutes Hours DOM Month DOW Year 1-7 1-12 1970- 1-31 SUN- 0-59 0-59 0-23 JAN- 2099 ?LW SAT DEC empty ?L# Monday, March 19, 2012
  • 69.
    Scheduling (require  ‘[immutant.jobs  :as  job]) (job/at  “name”  “3m”      #(println  “I  fire  after  3  minutes”)) (job/every  “name”  “1d”    #(println  “I  fire  once  a  day”)) Monday, March 19, 2012
  • 70.
    immutant.daemons long-­running  services Monday, March 19, 2012
  • 71.
    Daemons (require  ‘[immutant.daemons  :as  daemon]) (daemon/start  "name"  start-­fn  stop-­fn) Monday, March 19, 2012
  • 72.
    Daemons (def  response  (atom  nil)) (defn  start  []    (reset!  response        (twitter-­statuses-­filter              (terms)            url-­scraper))) (defn  stop  []      ((:cancel  (meta  @response)))) (daemon/start  "tweets"  start  stop                              :singleton  true) Monday, March 19, 2012
  • 73.
    Clustering simple  horizontal  scaling Monday, March 19, 2012
  • 74.
    Clustering $  lein  immutant  run  -­-­clustered Monday, March 19, 2012
  • 75.
    Clustering • Session  replication • Robust,  load-­balanced  message   distribution • HA  Singleton • HA  Jobs • Infinispan Monday, March 19, 2012
  • 76.
    mod_cluster • An  Apache  module  aware  of  JBoss • Reverse  proxy  via  AJP  or  HTTP[S] • Uses  load  statistics  and  deployment   availability  for  intelligent  routing • Optional  session  affinity • Failover Monday, March 19, 2012
  • 77.
  • 78.
    Coming  soon • Distributed  Transactions  (XA) • OpenShift  integration • Websockets • Better  remote  support • Domain  Mode  (cluster  management) Monday, March 19, 2012
  • 79.
    http://immutant.org #immutant   @immutants Monday, March 19, 2012