MONTREAL JUNE 30, JULY 1ST AND 2ND 2012ERRest in DepthPascal RobertMacTI.ca
The Menu•   Request/response loop•   Behavior changes•   Formats•   Transactions•   Same Origin Policy•   Date and time ma...
Request handling
Request               Application.dispatchRequestERXRouteRequestHandler(WOActionRequestHandler).handleR                   ...
performActionNamed
checkAccess()•   Default implementation in ERXRouteController does nothing•   Override it in your controller for security ...
performHtmlActionNamed•   Does <EntityName><ActionName>Page component exists?    •   No: fall back to controller    •   Ye...
shouldFailOnMissingHtmlPage•   Does the component was not found or dont implement    IEXRouteComponent?    •   If shouldFa...
performRouteActionNamed•   Try to find <actionName>Action method.    •   Not found? Try to find <actionName> method.    •   ...
performUnknownAction•   if (ERXRest.strictMode)    •   throw ERXNotAllowedException (HTTP code 405)•   else    •   throw F...
performActionWithArguments•   Will invoke the method with the arguments
Objects management
Objects in routes•   /ra/<entityName>/{entity:EntityName}•   routeObjectForKey(key)•   create(filter)•   update(object, filt...
routeObjectForKey•   {<keyName>:<keyType>} in route = keyType result =    routeObjectForKey(<keyName>)•   Object is obtain...
coerceValueToTypeNamed•   Where value is transformed to a object or primitive•   If its an EO or POJO, will use    ERXRest...
create(filter)•   Will call ERXRestClassDescriptionFactory.classDescriptionForEntityName•   Will call    IERXRestDelegate.F...
update(object, filter)•   As with create(filter), will simply call updateObjectWithFilter
updateObjectWithFilter•   Major method•   Will take content from request and update object (PUT request)•   Also used to p...
Response handling
response(object, filter)•   Will built up the object graph with    ERXRestRequestNode.requestNodeWithObjectAndFilter•   Wil...
requestNodeWithObjectAndFilter•   If primitive/simple object, will set the value•   If EO/POJO, will call _fillInWithObject...
_fillInWithObjectAndFilter•   If object is an array, method take itself•   If not array, will use objects delegate to call ...
response(format, responseNode)•   Returns result of ERXRouteResults(context, restContext, format,    responseNode)•   ERXR...
response(ERXRestFetchSpecification,                 filter)•   Useful to return list of objects ("index" action)•   ERXRestF...
response(int)•   Use that one to send a response without any content in the body•   Check ERXHttpStatusCodes
Theres a property for that
"id" key•   ERXRest.idKey : what to use instead of "id"    Default: {"id":2 }    ERRest.idKey=primaryKey {"primaryKey":2 }
"nil" key•   ERXRest.nilKey    To rewrite the "nil" attribute    Default: <someAttribute nil="true"/>    ERXRest.nilKey=ce...
"type" key•   ERXRest.typeKey    Allow you to change the name of the "type" attribute    Default: {"type":"NameOfEntity"} ...
ERXRest.pluralEntityNames•   Default is true•   If set to false, cant use pluralized names    Default: /ra/restEntities   ...
ERXRest.suppressTypeAttributesForSimpl                   eTypes•   Only for XML format•   Default value is false•   Defaul...
ERXRest.strictMode•   Default is: true•   For missing route, will send 405 (Not Allowed) code, if set to false,    will se...
ERXRest.routeCase•   ERXRest.routeCase=LowerCamelCase    /ra/restEntities•   ERXRest.routeCase=CamelCase    /ra/RestEntiti...
ERXRest.parseUnknownExtensions•   /ra/restEntities/3.fsdfsd•   If set to true (the default):    HTTP/1.1 200 Apple WebObje...
Formats
ERXRest.defaultFormat•   ERXRest.defaultFormat=json|xml|plist|html|...•   Let you specify the default format for all contr...
Format detection•   Format detection is in ERXRouteController.format()•   Order of detection    •   From extension (.json)...
Adding new format•   Your own private format? Use    ERXRestFormat.registerFormatNamed()•   Format useful for the commumit...
Same Domain Policy
Same Origin Policy•   Problem: browsers wont load data if client and server not on same    domain•   Numerous ways: window...
CORS•   Works with Gecko 1.9.1 (Firefox 3.5+), WebKit (Safari 4+, Google    Chrome 3+), Opera 12 and IE 8+•   Send extra h...
CORS preflightClient request:OPTIONS /resources/post-here/ HTTP/1.1Origin: http://foo.exampleAccess-Control-Request-Method:...
CORS•   ERXRest.accessControlAllowRequestHeaders•   ERXRest.accessControlAllowRequestMethods•   ERXRest.accessControlMaxAg...
window.name Transport•   Dojo use that trick•   Client send ?windowname=true in URL•   Enable it on server with:    ERXRes...
Status codes
Status code and exceptions•   ObjectNotAvailableException, FileNotFoundException,    NoSuchElementException: returns a 404...
Adding support for new data types•   Add a processor in _ERXJSONConfig•   Add support code in ERXRestUtils    •   isPrimiti...
MONTREAL JUNE 30, JULY 1ST AND 2ND 2012Q&A
Upcoming SlideShare
Loading in …5
×

ERRest in Depth

1,610 views

Published on

See how the request/response loop works in a ERRest context, and how to change the behavior of your REST services built with Project Wonder.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,610
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
22
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

ERRest in Depth

  1. 1. MONTREAL JUNE 30, JULY 1ST AND 2ND 2012ERRest in DepthPascal RobertMacTI.ca
  2. 2. The Menu• Request/response loop• Behavior changes• Formats• Transactions• Same Origin Policy• Date and time management
  3. 3. Request handling
  4. 4. Request Application.dispatchRequestERXRouteRequestHandler(WOActionRequestHandler).handleR equest YourController(ERXRouteController).performActionNamed
  5. 5. performActionNamed
  6. 6. checkAccess()• Default implementation in ERXRouteController does nothing• Override it in your controller for security check
  7. 7. performHtmlActionNamed• Does <EntityName><ActionName>Page component exists? • No: fall back to controller • Yes: Check if component implements IEXRouteComponent • Yes: return the component • No: fall back to controller
  8. 8. shouldFailOnMissingHtmlPage• Does the component was not found or dont implement IEXRouteComponent? • If shouldFailOnMissingHtmlPage() returns true, call performUnknownAction (will return a 404 NotFound) • Default is false, override it in your controller if needed.
  9. 9. performRouteActionNamed• Try to find <actionName>Action method. • Not found? Try to find <actionName> method. • Still nothing? Check for annotations. • Still nothing? Call performUnknownAction • Got something? Call performActionWithArguments
  10. 10. performUnknownAction• if (ERXRest.strictMode) • throw ERXNotAllowedException (HTTP code 405)• else • throw FileNotFoundException (HTTP code 404)
  11. 11. performActionWithArguments• Will invoke the method with the arguments
  12. 12. Objects management
  13. 13. Objects in routes• /ra/<entityName>/{entity:EntityName}• routeObjectForKey(key)• create(filter)• update(object, filter)
  14. 14. routeObjectForKey• {<keyName>:<keyType>} in route = keyType result = routeObjectForKey(<keyName>)• Object is obtained by ERXRestUtils.coerceValueToTypeNamed
  15. 15. coerceValueToTypeNamed• Where value is transformed to a object or primitive• If its an EO or POJO, will use ERXRestClassDescriptionFactory.classDescriptionForEntityName to find the class• Will call IERXRestDelegate.Factory.delegateForClassDescription().objectOfEntityWithI D()
  16. 16. create(filter)• Will call ERXRestClassDescriptionFactory.classDescriptionForEntityName• Will call IERXRestDelegate.Factory.delegateForClassDescription().createObjectOfEnti tyWithID to create a basic EO/POJO• Will call updateObjectWithFilter()
  17. 17. update(object, filter)• As with create(filter), will simply call updateObjectWithFilter
  18. 18. updateObjectWithFilter• Major method• Will take content from request and update object (PUT request)• Also used to populate new object (POST request)
  19. 19. Response handling
  20. 20. response(object, filter)• Will built up the object graph with ERXRestRequestNode.requestNodeWithObjectAndFilter• Will call response(format, responseNode)
  21. 21. requestNodeWithObjectAndFilter• If primitive/simple object, will set the value• If EO/POJO, will call _fillInWithObjectAndFilter
  22. 22. _fillInWithObjectAndFilter• If object is an array, method take itself• If not array, will use objects delegate to call primaryKeyForObject, and call _addAttributesAndRelationshipsForObjectOfEntity
  23. 23. response(format, responseNode)• Returns result of ERXRouteResults(context, restContext, format, responseNode)• ERXRouteResults.generateResponse() will actually generate the response in requested format
  24. 24. response(ERXRestFetchSpecification, filter)• Useful to return list of objects ("index" action)• ERXRestFetchSpecification allow you to set ordering, range, filtering and batching from request• Will also call response(format, responseNode)
  25. 25. response(int)• Use that one to send a response without any content in the body• Check ERXHttpStatusCodes
  26. 26. Theres a property for that
  27. 27. "id" key• ERXRest.idKey : what to use instead of "id" Default: {"id":2 } ERRest.idKey=primaryKey {"primaryKey":2 }
  28. 28. "nil" key• ERXRest.nilKey To rewrite the "nil" attribute Default: <someAttribute nil="true"/> ERXRest.nilKey=cestVide -> <someAttribute cestVide="true"/>• ERXRest.writeNilKey Skip the "nil" attribute Default: <someAttribute nil="true"/> ERXRest.writeNilKey=false -> <someAttribute nil="true"/>
  29. 29. "type" key• ERXRest.typeKey Allow you to change the name of the "type" attribute Default: {"type":"NameOfEntity"} ERXRest.typeKey=entityName {"entityName":"NameOfEntity"}• ERXRest.writeTypeKey If false, wont write the "type" attribute in the response ERXRest.writeTypeKey=false -> {id: 2, "type":"NameOfEntity"}
  30. 30. ERXRest.pluralEntityNames• Default is true• If set to false, cant use pluralized names Default: /ra/restEntities Set to false: /ra/restEntities
  31. 31. ERXRest.suppressTypeAttributesForSimpl eTypes• Only for XML format• Default value is false• Default rendering: <RestEntity primaryKey="1"> <someAttribute type = "integer">2</someAttribute> </RestEntity>• When set to false: <RestEntity primaryKey="1"> <someAttribute type = "integer">2</someAttribute>
  32. 32. ERXRest.strictMode• Default is: true• For missing route, will send 405 (Not Allowed) code, if set to false, will send 404 (Not Found)• POST requests: will send 201 (Created), if false will send 200 (OK)
  33. 33. ERXRest.routeCase• ERXRest.routeCase=LowerCamelCase /ra/restEntities• ERXRest.routeCase=CamelCase /ra/RestEntities• ERXRest.routeCase=LowercaseUnderscore /ra/rest_entities
  34. 34. ERXRest.parseUnknownExtensions• /ra/restEntities/3.fsdfsd• If set to true (the default): HTTP/1.1 200 Apple WebObjects Content-Type: text/html• If set to false: HTTP/1.0 400 Apple WebObjects
  35. 35. Formats
  36. 36. ERXRest.defaultFormat• ERXRest.defaultFormat=json|xml|plist|html|...• Let you specify the default format for all controllers• Can override it per controller: protected ERXRestFormat defaultFormat() { return ERXRestFormat.json(); }
  37. 37. Format detection• Format detection is in ERXRouteController.format()• Order of detection • From extension (.json). Set in ERXRouteRequestHandler.routeForMethodAndPath() • From the Content-Type header • Default format (defaultFormat() in controller)
  38. 38. Adding new format• Your own private format? Use ERXRestFormat.registerFormatNamed()• Format useful for the commumity? Add them to ERXRestFormat
  39. 39. Same Domain Policy
  40. 40. Same Origin Policy• Problem: browsers wont load data if client and server not on same domain• Numerous ways: window.name transport, JSONP and Cross-origin resource sharing (CORS)• CORS and window.name transport support is part of ERRest
  41. 41. CORS• Works with Gecko 1.9.1 (Firefox 3.5+), WebKit (Safari 4+, Google Chrome 3+), Opera 12 and IE 8+• Send extra headers to server• Client specifiy origin, requested HTTP verb and allowed headers, server returns allowed origin, methods, headers and max-age
  42. 42. CORS preflightClient request:OPTIONS /resources/post-here/ HTTP/1.1Origin: http://foo.exampleAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: X-PINGOTHERServer response:HTTP/1.1 200 OKAccess-Control-Allow-Origin: http://foo.exampleAccess-Control-Allow-Methods: POST, GET, OPTIONSAccess-Control-Allow-Headers: X-PINGOTHERAccess-Control-Max-Age: 1728000Client request:GET /resources/post-here/ HTTP/1.1Origin: http://foo.exampleServer response:HTTP/1.1 200 OKAccess-Control-Allow-Origin: http://foo.example
  43. 43. CORS• ERXRest.accessControlAllowRequestHeaders• ERXRest.accessControlAllowRequestMethods• ERXRest.accessControlMaxAge (default: 1728000)• ERXRest.accessControlAllowOrigin (* to allow all)
  44. 44. window.name Transport• Dojo use that trick• Client send ?windowname=true in URL• Enable it on server with: ERXRest.allowWindowNameCrossDomainTransport=true• Will wrap response in HTML code: <html><script type="text/javascript">window.name={"id": 4,"type":"RestEntity","someAttribute":"commit transaction"};</script></html>
  45. 45. Status codes
  46. 46. Status code and exceptions• ObjectNotAvailableException, FileNotFoundException, NoSuchElementException: returns a 404 (Not Found)• SecurityException: returns a 403 (Forbidden)• ERXNotAllowedException: returns a 405 (Method Not Allowed)• ERXValidationException, NSValidation.ValidationException: returns a 400 (Bad Request)• Anything else: returns a 500 (Internal Server Error)• Avoid sending 5xx codes if the client made a mistake!
  47. 47. Adding support for new data types• Add a processor in _ERXJSONConfig• Add support code in ERXRestUtils • isPrimitive() • coerceValueToString() • coerceValueToTypeNamed• For dates: add formatter in ERXRestUtils
  48. 48. MONTREAL JUNE 30, JULY 1ST AND 2ND 2012Q&A

×