RESTfully Async with Grails 2.3

74
© 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission. RESTfully Async with Grails 2.3 By Graeme Rocher Friday, September 13, 13

description

Speaker: Graeme Rocher In this talk Grails project lead, Graeme Rocher, will talk through the latest Async features offered by Grails and how they can be used to create elegant non-blocking REST APIs.

Transcript of RESTfully Async with Grails 2.3

Page 1: RESTfully Async with Grails 2.3

© 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission.

RESTfully Async with Grails 2.3By Graeme Rocher

Friday, September 13, 13

Page 2: RESTfully Async with Grails 2.3

© 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission.

RESTfully Async with Grails 2.3By Graeme Rocher

Friday, September 13, 13

Page 3: RESTfully Async with Grails 2.3

S P R I N G I O E X E C U T I O N :

Grails

Friday, September 13, 13

Page 4: RESTfully Async with Grails 2.3

Agenda

§Detailed Look at REST§Fun with Grails Async APIs§Summary / Q & A

Friday, September 13, 13

Page 5: RESTfully Async with Grails 2.3

Goals of REST Support in Grails 2.3

• Be Grails-y (i.e. dead simple)• Be Flexible (start simple, get deep)• Be pluggable (extend and conquer)• Be current (support latest techniques)

5

2.3

Friday, September 13, 13

Page 6: RESTfully Async with Grails 2.3

REST Features in 2.3

• RESTful URL Mappings• Domain Classes as REST

resources• Controllers as REST resources• Renderers and Binders

6

2.3

Friday, September 13, 13

Page 7: RESTfully Async with Grails 2.3

G R A I L S

DemoDomain classes as REST resources

Friday, September 13, 13

Page 8: RESTfully Async with Grails 2.3

REST: @Resource Transformation• Automatically exposes a

domain class as a REST resource

• Configurable formats• Configuration HTTP

methods

8Friday, September 13, 13

Page 9: RESTfully Async with Grails 2.3

REST: @Resource Transformation• Automatically exposes a

domain class as a REST resource

• Configurable formats• Configuration HTTP

methods

8

import  grails.rest.*

@Resourceclass  Person  {        String  name}

Friday, September 13, 13

Page 10: RESTfully Async with Grails 2.3

G R A I L S

DemoRESTful URL Mappings

Friday, September 13, 13

Page 11: RESTfully Async with Grails 2.3

REST: URL Mappings• RESTful Mappings

– Single or Multiple resources– Versioning– Nested resources

• New url-mappings-report command to mappings

10Friday, September 13, 13

Page 12: RESTfully Async with Grails 2.3

REST: Multiple Resources

11

HTTP Method URI ActionGET /books indexPOST /books saveGET /books/${id} showPUT /books/${id} updateDELETE /books/${id} delete

Friday, September 13, 13

Page 13: RESTfully Async with Grails 2.3

REST: Multiple Resources

11

"/books"(resources:'book')  

HTTP Method URI ActionGET /books indexPOST /books saveGET /books/${id} showPUT /books/${id} updateDELETE /books/${id} delete

Friday, September 13, 13

Page 14: RESTfully Async with Grails 2.3

REST: Singular Resources

12

HTTP Method URI Action

GET /book show

POST /book save

PUT /book update

DELETE /book delete

Friday, September 13, 13

Page 15: RESTfully Async with Grails 2.3

REST: Singular Resources

12

"/book"(resource:'book')  

HTTP Method URI Action

GET /book show

POST /book save

PUT /book update

DELETE /book delete

Friday, September 13, 13

Page 16: RESTfully Async with Grails 2.3

G R A I L S

DemoNested Resources

Friday, September 13, 13

Page 17: RESTfully Async with Grails 2.3

REST: Nested URL Mappings• You can nest resources or other URL mappings within

resources

14Friday, September 13, 13

Page 18: RESTfully Async with Grails 2.3

REST: Nested URL Mappings• You can nest resources or other URL mappings within

resources

14

"/books"(resources:'book')  {    "/authors"(resources:"author")}

"/books"(resources:  "book")  {        "/publisher"(controller:"publisher")}

Friday, September 13, 13

Page 19: RESTfully Async with Grails 2.3

REST: Nested Resources

15

HTTP Method URI ActionGET /books/${bookId}/authors indexPOST /books/${bookId}/authors saveGET /books/${bookId}/authors/${id} showPUT /books/${bookId}/authors/${id} updateDELETE /books/${bookId}/authors/${id} delete

Friday, September 13, 13

Page 20: RESTfully Async with Grails 2.3

REST: Nested Resources

15

"/books"(resources:'book')  {    "/authors"(resources:"author")}

HTTP Method URI ActionGET /books/${bookId}/authors indexPOST /books/${bookId}/authors saveGET /books/${bookId}/authors/${id} showPUT /books/${bookId}/authors/${id} updateDELETE /books/${bookId}/authors/${id} delete

Friday, September 13, 13

Page 21: RESTfully Async with Grails 2.3

G R A I L S

DemoVersioned Resources

Friday, September 13, 13

Page 22: RESTfully Async with Grails 2.3

REST: Versioned Resources• Version by URI• Version by “Accept-Version” header• Version by Media Type

17Friday, September 13, 13

Page 23: RESTfully Async with Grails 2.3

REST: Versioned Resources• Version by URI• Version by “Accept-Version” header• Version by Media Type

17

"/books"(version:'1.0',  resources:"book")"/books"(version:'2.0',  resources:"bookV2")

Friday, September 13, 13

Page 24: RESTfully Async with Grails 2.3

G R A I L S

DemoControllers as REST resources

Friday, September 13, 13

Page 25: RESTfully Async with Grails 2.3

REST: RestfulController Super Class• Implements methods for all the typical REST

operations (save, delete etc.)• Subclasses can override / augment as necessary

19Friday, September 13, 13

Page 26: RESTfully Async with Grails 2.3

REST: RestfulController Super Class• Implements methods for all the typical REST

operations (save, delete etc.)• Subclasses can override / augment as necessary

19

import  grails.rest.*class  PersonController  extends  RestfulController{        PersonController()  {          super(Person)        }}

Friday, September 13, 13

Page 27: RESTfully Async with Grails 2.3

REST: RestfulController for Nested Resources• Super class makes it easy to implement nested

resources

20Friday, September 13, 13

Page 28: RESTfully Async with Grails 2.3

REST: RestfulController for Nested Resources• Super class makes it easy to implement nested

resources

20

class  PersonController  extends  RestfulController{...protected  queryForResource(Serializable  id)  {

def  city  =  City.load(params.cityId)    Person.findByCityAndId(city,  id)          }

}

Friday, September 13, 13

Page 29: RESTfully Async with Grails 2.3

REST: Scaffolding 2.0• Scaffolding support now a plugin

– http://grails.org/plugin/scaffolding• Generated controllers now

RESTful• New generate-async-controller command for Async support

21Friday, September 13, 13

Page 30: RESTfully Async with Grails 2.3

G R A I L S

DemoRenderers

Friday, September 13, 13

Page 31: RESTfully Async with Grails 2.3

REST: Renderers• Rendering customizable in resources.groovy, just render

a Spring bean• JSON, XML, HAL, Atom, Vnd.Error renders included• Renderer can use any library (Jackson, GSON etc.)

23Friday, September 13, 13

Page 32: RESTfully Async with Grails 2.3

REST: Renderers• Rendering customizable in resources.groovy, just render

a Spring bean• JSON, XML, HAL, Atom, Vnd.Error renders included• Renderer can use any library (Jackson, GSON etc.)

23

import  grails.rest.render.json.*

beans  =  {   personRenderer(JsonRenderer,    Person)  {     excludes  =  ['class',  'age']   }}

Friday, September 13, 13

Page 33: RESTfully Async with Grails 2.3

REST: What is a Render?• Class that implements the Renderer interface

24Friday, September 13, 13

Page 34: RESTfully Async with Grails 2.3

REST: What is a Render?• Class that implements the Renderer interface

24

interface  Renderer<T>  extends  MimeTypeProvider{

       /**  @return  The  target  type    */        Class<T>  getTargetType()

       /**          *  Renders  the  object          */        void  render(T  object,  RenderContext  context)}

Friday, September 13, 13

Page 35: RESTfully Async with Grails 2.3

REST: Container Renderers• Container renderers render containers (Lists, Maps,

Errors) of a particular type• You want different output from a single resources vs

viewing multiple

25Friday, September 13, 13

Page 36: RESTfully Async with Grails 2.3

REST: Container Renderers• Container renderers render containers (Lists, Maps,

Errors) of a particular type• You want different output from a single resources vs

viewing multiple

25

interface  ContainerRenderer<C,  T>  extends  Renderer<C>{

       /*  The  generic  type  of  the  container*/        Class<T>  getComponentType()}

Friday, September 13, 13

Page 37: RESTfully Async with Grails 2.3

G R A I L S

DemoHypermedia & Mime / Media Types

Friday, September 13, 13

Page 38: RESTfully Async with Grails 2.3

REST: Hyper Media and Mime Types• Declare Mime Types in Config.groovy• Don’t declare new types first!

27Friday, September 13, 13

Page 39: RESTfully Async with Grails 2.3

REST: Hyper Media and Mime Types• Declare Mime Types in Config.groovy• Don’t declare new types first!

27

grails.mime.types  =  [        all:                      '*/*',        person:  "application/vnd.foo.org.person+json",        people:    "application/vnd.foo.org.people+json",        

Friday, September 13, 13

Page 40: RESTfully Async with Grails 2.3

REST: Hyper Media and Mime Types• Define Renderers that use those types in resources.groovy

28Friday, September 13, 13

Page 41: RESTfully Async with Grails 2.3

REST: Hyper Media and Mime Types• Define Renderers that use those types in resources.groovy

28

def  personMimeType  =        new  MimeType("application/vnd.foo.org.person+json")beans  =  {   personRenderer(JsonRenderer,                    Person,                    personMimeType)

}

Friday, September 13, 13

Page 42: RESTfully Async with Grails 2.3

G R A I L S

DemoVersioning with Hyper Media

Friday, September 13, 13

Page 43: RESTfully Async with Grails 2.3

REST: Hyper Media Versioning• You can version custom media types and use the media

type to render different outputs

30Friday, September 13, 13

Page 44: RESTfully Async with Grails 2.3

REST: Hyper Media Versioning• You can version custom media types and use the media

type to render different outputs

30

def  personMimeType  =        new  MimeType("application/vnd.foo.org.person+json",

     [v:  "1.0"]  )beans  =  {   personRenderer(JsonRenderer,                    Person,                    personMimeType)

}

Friday, September 13, 13

Page 45: RESTfully Async with Grails 2.3

G R A I L S

DemoHAL Support

Friday, September 13, 13

Page 46: RESTfully Async with Grails 2.3

REST: Hyper Media with HAL• HAL is a standardized format used in conjunction with

HATEOS principals

32Friday, September 13, 13

Page 47: RESTfully Async with Grails 2.3

REST: Hyper Media with HAL• HAL is a standardized format used in conjunction with

HATEOS principals

32

def  personMimeType  =        new  MimeType("application/vnd.foo.org.person+json",

     [v:  "1.0"]  )beans  =  {   personRenderer(HalJsonRenderer,                    Person,                    personMimeType)}

Friday, September 13, 13

Page 48: RESTfully Async with Grails 2.3

G R A I L S

DemoBinders / BindingSource

Friday, September 13, 13

Page 49: RESTfully Async with Grails 2.3

REST: Binding / BindingSource• If you define a custom render you may need to define a

custom binding source to make binding work

34Friday, September 13, 13

Page 50: RESTfully Async with Grails 2.3

REST: Binding / BindingSource• If you define a custom render you may need to define a

custom binding source to make binding work

34

protected  DataBindingSource                          createBindingSource(Reader  reader)  {   def  json  =  JSON.parse(reader)   def  map  =  [     firstName:json.first_name,     lastName:json.last_name   ]   new  SimpleMapDataBindingSource(map)}

Friday, September 13, 13

Page 51: RESTfully Async with Grails 2.3

Goals of Async Support in Grails 2.3

• Be Grails-y (i.e. dead simple)• Be Flexible (start simple, get deep)• Be pluggable (extend and conquer)• Be current (support latest techniques)

35

2.3

Friday, September 13, 13

Page 52: RESTfully Async with Grails 2.3

Async Features in 2.3

• Async Primitives (Promises, Lists, Maps etc.)

• Async Data (GORM)• Async Everywhere (Tasks)• Async Request Handling

36

2.3

Friday, September 13, 13

Page 53: RESTfully Async with Grails 2.3

G R A I L S

DemoAsync Primitives

Friday, September 13, 13

Page 54: RESTfully Async with Grails 2.3

Async: Promise Primitives• Foundational API for Async

programming• Includes notion of Promise• Ability to combine / chain

promises

38Friday, September 13, 13

Page 55: RESTfully Async with Grails 2.3

Async: Promise Primitives• Foundational API for Async

programming• Includes notion of Promise• Ability to combine / chain

promises

38

import  static  grails.async.Promises.*

def  p1  =  task  {  2  *  2  }def  p2  =  task  {  4  *  4  }def  p3  =  task  {  8  *  8  }assert  [  4,  16,  64  ]  ==  waitAll(p1,  p2,  p3)

Friday, September 13, 13

Page 56: RESTfully Async with Grails 2.3

Async: Promise Chaining• Chain promises to formulate a value asynchronously

39Friday, September 13, 13

Page 57: RESTfully Async with Grails 2.3

Async: Promise Chaining• Chain promises to formulate a value asynchronously

39

import  static  grails.async.Promises.*import  static  grails.async.*Promise  p  =        task  {  2  *  2  }  <<  {  it  *  4  }  <<  {  it  *  8  }

p.onComplete  {  Integer  value  -­‐>        println  "Total:  $value"}  

Friday, September 13, 13

Page 58: RESTfully Async with Grails 2.3

Async: Promise Chaining• Create list and map data structures from promises!

40Friday, September 13, 13

Page 59: RESTfully Async with Grails 2.3

Async: Promise Chaining• Create list and map data structures from promises!

40

import  static  grails.async.Promises.*import  static  grails.async.*PromiseList  p  =        task  {  2  *  2  }  <<  {  it  *  4  }  <<  {  it  *  8  }

p.onComplete  {  Integer  value  -­‐>        println  "Total:  $value"}  

Friday, September 13, 13

Page 60: RESTfully Async with Grails 2.3

Async: Promise Factory• Override the creation of promise instances

– Plugin in Reactor– Change to synchronous promises for testing

41Friday, September 13, 13

Page 61: RESTfully Async with Grails 2.3

Async: Promise Factory• Override the creation of promise instances

– Plugin in Reactor– Change to synchronous promises for testing

41

import  org.grails.async.factory.*import  grails.async.*Promises.promiseFactory  =      new  SynchronousPromiseFactory()

Friday, September 13, 13

Page 62: RESTfully Async with Grails 2.3

Async: @DelegateAsync Transform• Transform any synchronous

API into an asynchronous one

• Takes each method and returns a promise

42Friday, September 13, 13

Page 63: RESTfully Async with Grails 2.3

Async: @DelegateAsync Transform• Transform any synchronous

API into an asynchronous one

• Takes each method and returns a promise

42

import  grails.async.*

class  AsyncBookService  {      @DelegateAsync        BookService  bookService}

Friday, September 13, 13

Page 64: RESTfully Async with Grails 2.3

G R A I L S

DemoAsync Data (GORM)

Friday, September 13, 13

Page 65: RESTfully Async with Grails 2.3

Async: GORM• Makes all GORM methods

async• Each method returns a Promise

• Deals with binding session to background thread

• Works across all datastores (MongoDB, GORM for REST etc.)

44Friday, September 13, 13

Page 66: RESTfully Async with Grails 2.3

Async: GORM• Makes all GORM methods

async• Each method returns a Promise

• Deals with binding session to background thread

• Works across all datastores (MongoDB, GORM for REST etc.)

44

def  p1  =  Person.async.get(1)def  p2  =  Person.async.get(2)def  p3  =  Person.async.get(3)

def  results  =                waitAll(p1,  p2,  p3)

Friday, September 13, 13

Page 67: RESTfully Async with Grails 2.3

Async: GORM Tasks• Batch up a bunch of Grails queries to be executed

asynchronously

45Friday, September 13, 13

Page 68: RESTfully Async with Grails 2.3

Async: GORM Tasks• Batch up a bunch of Grails queries to be executed

asynchronously

45

def  promise  =  Person.async.task  {        withTransaction  {              def  person  =  findByFirstName("Homer")              person.firstName  =  "Bart"              person.save(flush:true)                }}Person  updatedPerson  =  promise.get()

Friday, September 13, 13

Page 69: RESTfully Async with Grails 2.3

G R A I L S

DemoAsync Request Handling

Friday, September 13, 13

Page 70: RESTfully Async with Grails 2.3

Async: Request Processing• Handle requests

asynchronously• Uses Servlet 3.0 async

under the covers• Create asynchronous

models

47Friday, September 13, 13

Page 71: RESTfully Async with Grails 2.3

Async: Request Processing• Handle requests

asynchronously• Uses Servlet 3.0 async

under the covers• Create asynchronous

models

47

import  static  grails.async.Promises.*

class  PersonController  {    def  index()  {      tasks  books:  Book.async.list(),                total:  Book.async.count(),                otherValue:  {                      //  do  hard  work                }      }}

Friday, September 13, 13

Page 72: RESTfully Async with Grails 2.3

REST: Generating Async Controllers• New scaffolding can generate an

example Async controller – http://grails.org/plugin/scaffolding

• Use generate-async-controller command

48Friday, September 13, 13

Page 73: RESTfully Async with Grails 2.3

Q & AREST & Async

3.0

Friday, September 13, 13

Page 74: RESTfully Async with Grails 2.3

Learn More. Stay Connected.

Web: grails.orgTwitter: twitter.com/grailsframeworkLinkedIn: http://linkedin.com/groups/Grails-User-Group-39757 Google +: https://plus.google.com/communities/109558563916416343008

Friday, September 13, 13