Note
This is an experimental feature.
qx.io.rest.Resource allows to encapsulate the specifics of a REST interface. Rather than requesting URLs with a specific HTTP method manually, a resource representing the remote resource is instantiated and actions are invoked on this resource. A resource with its actions can be configured declaratively or programatically.
Given a REST-like interface with URLs that comply to the following pattern.
GET /photo/{id}
PUT /photo/{id}
DELETE /photo/{id}
GET /photos
POST /photos
Note {id} stands for a placeholder.
This interface comprises of two resources: photo and photos.
To declare the specifics of the REST interface declaratively, pass a description to the constructor.
// Singular resource
var photo = new qx.io.rest.Resource({
// Retrieve photo
get: {
method: "GET",
url: "/photo/{id}"
},
// Update photo
put: {
method: "POST",
url: "/photo/{id}"
},
// Delete photo
del: {
method: "DELETE",
url: "/photo/{id}"
}
});
// Plural resource
var photos = new qx.io.rest.Resource({
// Retrieve list of photos
get: {
method: "GET",
url: "/photos"
},
// Create photo
post: {
method: "POST",
url: "/photos"
}
});
Or programmatically, for each action.
var photo = new qx.io.rest.Resource();
photo.map("get", "GET", "/photo/{id}");
Once configured, actions can be invoked. They are invoked by calling a method that is dynamically added to the resource on configuration of the action.
photo.get({id: 1});
// Alternatively: photo.invoke("get", {id: 1});
// --> GET /photo/1
photos.get();
// Alternatively: photos.invoke("get");
// --> GET /photos
When an action is invoked, an appropriate request is configured and send automatically.
If the URL contains parameters, the position where the parameters should be inserted can be specified by using URI templates. Parameters are optional unless a check is defined. A default value can be provided.
var photo = new qx.io.rest.Resource();
photo.map("get", "GET", "/photo/{id}/{size=medium}", {id: qx.io.rest.Resource.REQUIRED});
photo.get({id: 1, size: "large"});
// --> GET /photo/1/large
photo.get({id: 1});
// --> GET /photo/1/medium
photo.get();
// --> Error: Missing parameter 'id'
Events are fired by the resource when the request was successful or any kind of error occurred. There are general resource events and action specific events. Handlers receive a qx.event.type.Rest event that, among other properties, includes the response.
photo.get({id: 1});
photo.put({id: 1});
// "success" is fired when any request associated to resource receives a response
photos.addListener("success", function(e) {
e.getAction();
// --> "get" or "put"
});
// "getSuccess" is fired when the request associated to the get action receives a response
photos.addListener("getSuccess", function(e) {
e.getAction();
// --> "get"
});
If the same action should be invoked multiple times and the events fired for each request be handled differently, it is possible to remember the id of the action’s invocation. The Rest event includes this id.
var getPhotoId = photo.get({id: 1});
var getLargePhotoId = photo.get({id: 1, size: "large"});
photo.addListener("getSuccess", function(e) {
if (e.getId() === getLargePhotoId) {
// Handle large photo
}
});
Helpers make it easy to accomplish common tasks when working with requests.
A qx.data.store.Rest store can be attached to an action. Whenever a response is received, the model property of the store is updated with the marshaled response.
var store = new qx.data.store.Rest(photos, "get");
var list = new qx.ui.form.List();
var controller = new qx.data.controller.List(null, list);
store.bind("model", controller, "model");
photos.longPoll("get");