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

RESTfully Async with Grails 2.3

Embed Size (px)

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.

Citation preview

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