ratpack web framework

40
Ratpack Web Framework Dan Woods

Upload: daniel-woods

Post on 17-Aug-2015

349 views

Category:

Technology


0 download

TRANSCRIPT

Ratpack  Web  Framework  

Dan  Woods  

Senior  Engineer  at    The  Groundwork  

@danveloper  on  Twi.er  

/danveloper  on  GitHub  

Learning  Ratpack          

publica=on  Fall  2015  

Shameless  Self  Promo=on…  

Quick  Overview  

•  A  high-­‐throughput,  reac=ve  web  framework  for  the  JVM  

•  Built  on  Java  8  (required)  and  comes  with  a  Groovy  DSL  

•  Great  support  for  microservices  /  Twelve  Factor  apps  

•  Rapid  produc=vity  

Quick  Start  

•  Groovy  DSL  is  the  path  of  least  resistance  •  App  can  be  built  into  a  standalone,  runnable  Groovy  script  

•  Rapid  prototyping  

What  is  this  doing?  

•  Imports  the  DSL  via  ratpack.groovy.Groovy.ratpack  

•  The  closure  supplied  is  the  defini3on  •  Defini=on  consists  of  serverConfig,  bindings,  and  handlers  

•  App  defini=on  infers  reasonable  defaults  for  serverConfig  and  bindings  

What  is  this  doing?  

Handler  Chain  

•  A  pipeline  for  request  processing  •  The  “edge”  of  an  applica=on  •  Defines  request  flow  and  terminal  handlers  •  Handlers  can  be  thought  of  in  equivalent  terms  to  servlets  and  servlet  filters  

Handler  Chain  

Diagram  courtesy  of  Andrey  Adamovich:  h_ps://twi_er.com/codingandrey    

Handlers  

•  Two  types  of  handlers:  request  flow  and  terminal  

•  Request  flow  handlers  provide  flow  control  in  processing  

•  Terminal  handlers  process  and  respond  to  a  request  

Terminal  Handlers  

•  Bound  to  HTTP  verb(s)  and  request  path  •  Chain  API  provides  seman=c  methods  for  binding  to  verb  

Method   Descrip.on   Usage  

all   Handler  is  executed  for  all  requests  within  its  chain  

all  {      render  “Hello  World!”  }  

get(path)   Handler  for  HTTP  GET  requests.  Path  op=onal.  

get(“foo”)  {      render  “Hello  Foo!”  }    

post(path)   Handler  for  HTTP  POST  requests.  Path  op=onal.  

post(“foo”)  {      def  json  =  request.body.text      …  }    

put(path)   Handler  for  HTTP  PUT  requests.  Path  op=onal.    

put(“foo”)  {      def  json  =  request.body.text      …  }    

patch(path)   Handler  for  HTTP  PATCH  requests.  Path  op=onal.    

patch(“foo”)  {      def  json  =  request.body.text      ...  }    

delete(path)   Handler  for  HTTP  DELETE  requests.  Path  op=onal.    

delete(“:id”)  {      def  id  =  request.pathTokens.id      ...  }  

A  Caveat  to  Handlers  

•  Only  a  single  handler  can  be  bound  for  any  given  HTTP  request  path  

•  You  must  use  request  flow  mechanisms  to  bind  mul=ple  handlers  for  a  path  

Request  Flow  Handlers  

•  Terminal  handlers  get  nested  •  Allow  host  binding,  prefix  binding,  decision  rou=ng,  method  rou=ng,  content  type  nego=a=on  

•  Can  be  defined  within  the  handler  chain  or  handlers  themselves  

Prefix  Handler  

•  Creates  a  sub-­‐chain  bound  to  a  prefixed  request  path  

•  Allows  handlers  to  be  defined  within  the  context  of  the  prefix  

•  Makes  it  easy  to  scope  a  handler  chain  

The  when  Handler  

•  Creates  a  sub-­‐chain  bound  to  a  prefixed  request  path  

•  Allows  handlers  to  be  defined  within  the  context  of  the  prefix  

•  Makes  it  easy  to  scope  a  handler  chain  

Method  Rou=ng  

•  Nested  handler  type  (handlers  within  a  handler)  

•  Uses  the  byMethod  call  within  a  handler  •  Must  be  bound  within  an  all  handler  type  

Content  Type  Nego=a=on  

•  Nested  handler  type  (handlers  within  a  handler)  

•  Uses  the  byContent  call  within  a  handler  •  Routed-­‐to  according  to  request’s  Accept  header  

•  Chain  for  content  type  handlers  •  Seman=cs  for  common  content  types  (json,  xml,  html,  plainText)  

Method   Descrip.on  

json   Called  when  application/json  is  specified  in  Accept  header  

xml   Called  when  application/xml  is  specified  in  Accept  header  html   Called  when  text/html  is  specified  in  Accept  header  plainText   Called  when  text/plain  is  specified  in  Accept  header  

 type(String)   Called  when  the  provided  string  matches  the  Accept  header  

 noMatch   Called  when  the  Accept  header  is  specified,  but  no  handler  is  

bound  for  the  given  type    

•  Caveat:  the  first  handler  in  the  byContent  chain  is  favored  when  no  Accept  header  is  present  

 

Content  Type  Nego=a=on  

Project  Structure  

•  OOTB  Support  for  Gradle  build  system  •  App  structure  follows  Java  conven=ons  •  Groovy  apps  can  s=ll  be  built  as  scripts  •  Apps  can  be  defined  from  within  a  main  class  

Gradle  Support  

•  Add  the  io.ratpack:ratpack-­‐gradle:<version>  to  your  buildscript  classpath  

•  Apply  the  io.ratpack.ratpack-­‐{groovy,java}  plugin  to  your  buildscript  

•  ./gradlew  run  to  see  your  app  in  ac=on!  

Framework  Dependencies  

•  Use  the  plugin  helper  method  to  bring  in  framework  deps  

•  Framework  deps  are  resolved  by  their  unqualified  name  

•  As  simple  as  specifying  ratpack.dependency(name)  in  dependencies  block  

Main  Class  Apps  

•  Any  project  can  build  a  main  class  and  use  that  as  the  entry  point  

•  Use  the  ratpack.server.RatpackServer  factory  to  define  your  applica=on  

•  Java  8  apps  must  use  a  main  class  

Dependency  Injec=on  

•  DI  in  Ratpack  is  abstracted  through  the  Registry  

•  Request  handling  code  is  FP  style,  so  should  remain  stateless  

•  The  Context  given  to  each  handler  allows  resolu=on  of  components  

Dependency  Injec=on  

•  OOTB  support  for  Guice  and  Spring  Boot  •  Groovy  DSL  has  Guice  fixtures  pre-­‐baked  •  The  bindings  block  allows  you  to  bind  components  in  your  app  

Dependency  Injec=on  

•  Groovy  DSL:  Components  injected  into  handlers  through  varargs  

•  Java  API:  components  are  resolved  through  Context.get(Class)  

•  Note  that  non-­‐Groovy  apps  need  to  include  the  ratpack-­‐guice  framework  dependency  

Registries  

•  Registries  can  be  built  on-­‐the-­‐fly  within  the  handler  chain  

•  Latest  binding  will  be  resolved  first  •  Allows  apps  to  register  and  resolve  components  according  to  proper=es  of  a  request  

Tes=ng  

•  Ratpack  provides  fixtures  for  func=onal,  integra=on,  and  unit  tes=ng  

•  Can  quickly  get  high  test  coverage  with  li_le  effort  

•  EmbeddedApp  fixture  can  be  integrated  to  ameliorate  hard-­‐to-­‐test  or  legacy  apps  

Non-­‐Blocking  Paradigm  

•  Ratpack  uses  NIO  to  garner  high  throughput  •  Maintains  discrete  request-­‐taking  and  blocking  thread  pools  

•  Request-­‐taking  threads  must  not  block  •  Blocking  APIs  are  able  to  be  made  async  through  the  Context.blocking()  mechanism  

Building  Async  APIs  

•  Build  your  APIs  around  Ratpack  Promise  types  •  This  gives  you  flexibility  in  determining  in  processing  capacity  (blocking/computa=on)  

•  Promises  ensure  that  the  Ratpack  knows  when  your  app  is  async  processing  

Reac=ve  Programming  

Reac3ve  programming  is  a  technique  by  a  processing  func3on  requests  data  from  a  

producing  func3on,  a  single  element  at  a  3me.  Mul3ple  elements  are  delivered  through  a  pipeline,  wherein  one  or  many  func3ons  can  

affect  the  flow  and  form  of  data.  

Reac=ve  Programming  

The  request  for  data  starts  here  

Transforming  func=on  Call  for  a  data  element    

Call  for  a  data  element    

Call  for  a  data  element    

Filtering  func=on  

Producing  func=on  (will  send  elements  down  the  pipeline  when  requested)  

Reac=ve  Programming  

•  Data  is  not  “observed”  by  down-­‐pipeline  func=ons  un=l  the  above-­‐pipeline  func=ons  supply  it  

•  Push  vs.  Pull  data  element  retrieval  methodology  

•  Best  suited  for  async  processing,  where  data  is  gathered  on-­‐demand  (not  in  advance)  

Reac=ve  Programming  

•  Promises  are  reac=ve,  in  that  they  send  data  only  when  it  is  requested  

•  Promises  will  only  ever  “emit”  a  single  item  into  the  processing  pipeline  (whether  it  be  a  list  of  data  elements  or  a  single  data  element  itself)  

Reac=ve  Programming  

•  Ratpack  has  extensive  support  for  interopera=ng  with  RxJava  

•  Provides  RxJava  with  a  scheduler  for  processing  work  from  Observables  

•  Observables  can  emit  one  or  more  data  elements  through  the  pipeline  to  cons=tute  a  “stream”  of  data  

•  Ideal  for  robust  async  API  layers  

Configura=on  

•  Support  for  building  typed  configura=on  models  from  a  variety  of  sources  

•  Configura=on  can  come  from  JSON,  YAML,  Java  Proper=es  

•  Microservice  and  produc=on  configs  can  pull  configura=on  from  sys  props  and  environment  variables  

Addi=onal  Framework  Features  

•  Non-­‐blocking/Async  HTTP  client  •  Support  for  Hystrix  for  fault  tolerance  across  microservices  

•  Database  connec=on  pooling  (HikariCP)  •  Sessions  and  Cookies  •  Security  (Pac4j)  •  Content  serving  (built-­‐in  and  Asset  Pipeline)  •  Metrics  (CodaHale)  •  Asynchronous  health  checks  

Packaging  

•  Builds  leverage  the  Gradle  applica=on  plugin  •  Na=ve  support  for  crea=ng  tar  or  zip  distribu=on  packages  for  deployment  

•  Can  be  overlayed  with  the  Shadow  Jar  plugin  to  build  “fat  jars”  

•  Perfect  for  cloud-­‐na=ve  microservice  deployments  

So  Why  Should  I  Care?  

•  Ratpack  is  FAST  •  A  single  instance  of  Ratpack  can  support  up  to  800,000  concurrent  requests  per  second*  –  h_ps://gist.github.com/danveloper/db888be3519966976368  

•  Provides  applica=on  structure  to  non-­‐blocking  underpinnings  

•  App  packages  are  standalone,  runnable,  and  small  

Ques=ons?