2. Overview
• The basics
• Security
• Dojo and ERRest
• Using Dojo's DataGrid and JsonRestStore
• Client-side validation with JSON Schema
• Transactions
• Todo
4. The basics
• Think of REST as direct actions with specific action per HTTP
methods (GET, POST, etc.).
• ERRest will create/modify EOs based on data sent by the client,
not need to call request().formValueForKey().
• No envelope on the request, if meta-data is needed, it will use
the HTTP headers or parameters in the URL.
5. HTTP methods and actions
HTTP method Action
GET Read (fetch)
POST Create
PUT Update
DELETE Delete
* This slide was taken from Mike's WOWODC 2009 session
6. One gotcha : you need to use the HTTP adaptor
from Wonder or WO 5.4 for DELETE and PUT
support.
7. Basic architecture of ERRest
• ERRest uses the same architecture as the REST support in Ruby
on Rails.
• You build controllers for each entity you want to offer as REST
services.
• You create routes that you register in the REST request hander,
and the routes are connected to controllers.
• Check Mike's session from WOWODC West 2009 for more
details on the architecture.
8. Routes and actions
HTTP method URL Action
GET /movies fetch all movies
GET /movies/100 fetch movie with id 100
POST /movies create new movie object
PUT /movies/100 update movie id 100
DELETE /movies/100 delete movie id 100
* This slide was taken from Mike's WOWODC 2009 session
9. ERXDefaultRouteController
• Provides abstract methods for all REST actions.
• One line registration in the REST request handler
10. ERXRestFormat
• Parse the request and write the response in different formats :
• JSON
• JS (same as JSON, but with a different MIME type)
• ASCII plist (iPhone/OS X apps!)
• XML
• SproutCore (JSON with specific properties)
• Rails (XML, but with a different format)
• Some chocolate and nuts framework that we can't talk about
• Default format is XML
11. Filtering
• You may not want to return all attributes and all relationships
attributes in your response.
• Filtering works with ERXKeyFilter.
• You can have an different filter per route.
14. Security
• You don't want anyone to be able to delete any objects...
• The most popular way to do this is with "authkeys".
• Ask users to send the key in the URL...
• ... and use request().stringFormValueForKey to get it
• Use HTTPS when using auth keys!
16. Same Origin Policy
• XMLHttpRequest won't load (but will fetch) data if the
XMLHttpRequest call is not in the same domain as the REST
service, it's the Same Origin Policy.
• 4 options to get over that policy : window.name, HTTP Access
Control, proxing or JSONP.
17. Same Origin Policy
• HTTP Access Protocol sends a OPTIONS HTTP call to the
service with specific headers.
• Access-Control-Request-Method
• Access-Control-Request-Headers
• Origin
• REST service must reply to the OPTIONS request with some
options
• Supported by Safari 4+, Firefox 3.5+, IE 8 and Chrome 5
18. Same Origin Policy
To support HTTP Access Control, you have to add a route for the
OPTIONS method:
restReqHandler.insertRoute(new ERXRoute(Movie.ENTITY_NAME,"/movies",
ERXRoute.Method.Options,MoviesController.class, "options"));
Add the optionsAction method in your controller:
public WOActionResults optionsAction() throws Throwable {
ERXResponse response = new ERXResponse();
response.setHeader("*", "Access-Control-Allow-Origin");
response.setHeaders(this.request().headersForKey("Access-Control-Request-Method"), "Access-
Control-Allow-Methods");
response.setHeaders(this.request().headersForKey("Access-Control-Request-Headers"), "Access-
Control-Allow-Headers");
response.setHeader("1728000", "Access-Control-Max-Age");
return response;
}
19. Same Origin Policy
You also need to set the headers in the response of your other
actions :
public WOActionResults indexAction() throws Throwable {
...
WOResponse response = response(editingContext(), Movie.ENTITY_NAME, movies, showFilter
()).generateResponse();
response.setHeader("*", "Access-Control-Allow-Origin");
return response;
}
20. Same Origin Policy
• window.name uses a iFrame to communicate with the REST
service, and the XMLHTTPRequest fetch the data locally from
the iFrame window.name property.
• Adds "windowname=true" to the query
• Response must be text/html wrapped in script tag
• JSONP is the same concept, but use a <script> tag instead of an
iFrame.
• Good alternative for older browsers that don't support HTTP
Access Control.
22. Same Origin Policy
• Last option : proxing on the client side, where the client
XMLHTTPRequest makes its request to a local service (WO, JSP,
PHP, etc.) and that service connects to your service.
24. DOJO
• First release in March 2005
• Managed by the Dojo Foundation, backed by IBM, Sun and others
• Dual licensed : BSD and Academic Free
• Latest release is 1.5, on July 15th 2010
25. DOJO
• Lots of data widgets (Grid, Tree, etc.) and stores (JSON, Flickr,
Picasa, etc.).
• Create a store that use the dojo.data system and it will be
available for all data widgets like the DataGrid.
• Switching to a different store might require only one line of
change.
26. JsonRestStore
• Easy to use data store.
dojo.require("dojox.data.JsonRestStore");
var jsonStore = new dojox.data.JsonRestStore({ target: "/ra/movies" });
• store.save() method will contact your REST service to save
changes.
• Must change the default format in your REST controller to
JSON.
protected ERXRestFormat defaultFormat() { return ERXRestFormat.JSON; }
27. DataGrid
• DataGrid displays data from a data store in a table.
• Columns are resizable and sortable.
• Paging is supported.
• Rows are editable.
28. DataGrid paging
• In the data grid properties, add :
rowsPerPage="a int value"
• Dojo will send an extra header when paging is required :
Range: 0-19
• The REST service must reply with :
Content-Range: 0-19/99
29. Adding new objects
• We can add new objects to the store, they will be created
server-side when the save() method is called on the store.
• The new object have to be added to the store with the newItem
() method.
30. JSON Schema
• Define the structure of JSON data.
• List of properties for the JSON object. Type can be string,
number, integer, object, array, enum, etc.
• You can reference other schemas, including schemas specified at
full URLs.
• Dojo can use it to perform client side validation.
• We can call it WSDL for JSON, with less chat.
36. JSON Schema
• With JSON schema, when adding new items to the store,
validation will be done client-side, no need to contact the server
for basic validation.
37. Transactions
• When store.save() is called, if multiple objects have to be saved,
Dojo will add a Transaction, a Seq-Id and a Client-Seq-Id headers.
• The value of the header is either Open or Commit.
• Seq-Id is a integer with the transaction number.
• Client-Seq-Id is a unique id per browser page.
• Only one problem : transactions are not sent in order!
• Let see this in action!
39. Todo
• JSON Referencing
• HTML5 Storage
• Service Mapping Description (SMD)
40. JSON Referencing
• Instead of putting the content of related objects in the root
object, you put references to those objects.
• Dojo will do lazy-loading of the related objects, eg it will fetch
them when needed.
• Data will look like this :
{
"title": "title",
"studio": {"$ref": "/studio/1" }
}
• http://www.sitepen.com/blog/2008/11/21/effective-use-of-jsonreststore-referencing-lazy-loading-
and-more/
41. HTML5 Storage
• Dojo 1.5 have support for HTML5 local storage, but I didn't find
the documention for it.
• Previous Dojo versions have OfflineRest, but it uses Flash (doh!)
as the data storage engine for WebKit browsers, and Google
Gears on Firefox.
42. Service Mapping Description
• SMD describes available services, just like WSDL for SOAP.
• JSON Schema is part of SMD.
• Look like this:
{
target:"/jsonrpc",
transport:"POST",
envelope:"JSON-RPC-1.2",
SMDVersion:"2.0",
services: {
add : { // define a service to add two numbers
parameters: [
{name:"a",type:"number"}, // define the two parameters
{name:"b",type:"number"}
],
returns:{"type":"number"}
}
}
• http://www.sitepen.com/blog/2008/03/19/pluggable-web-services-with-smd/