Broadcast on Broadcast off
The Documentation for Project Zero has moved. Please update your bookmarks to: http://www.projectzero.org/documentation/
Table of
Contents...
Hide

Project Zero Developer’s Guide

Concepts and components
Basic concepts overview
Event processing
Writing Java handlers
Writing Groovy handlers
Firing events
Global Context
Global Context reference
Application directory layout
Virtualized directories
Assemble
PHP
Features and configuration
Configuration
Debugging
Dependencies
Packaging
Application classpath
Logging and tracing
RESTful resources
RESTful documentation
File serving
Response rendering
Validators and validation
HTTP error handling
Calling a remote resource
Using the Connection API
Sending an email using EmailConnection
Configuring destinations
Configuring protocols
Configuring connection handlers
Creating a connection handler
Creating a custom protocol transport
Simple logging connection handlers
Protocol reference
Client programming with Dojo
Runtime options
Deployment modifications
HTTP configuration
SSL configuration
Proxy configuration
Extending the CLI
Security considerations
Authentication
OpenID authentication
Extending security
Security tokens
CSRF prevention support
Extending token support
Leveraging TAI
User service
File based user service
LDAP user service
Extending user service
Security Utilities
Leveraging XOREncoder
Extensions
Atom support
RSS support
JSON support
XMLEncoder
REST to SOAP extension
URIUtils
Developer Web tools
Database setup tools
Configuring data access
Common query patterns
Advanced query patterns
Update patterns
Local database transactions
Extending data access
Configuration vendor differences
PHP data access
Resource model
Configuring ZRM
Resource model declaration
Programmatic model API
HTTP REST API
A ZRM mini tutorial
Active content filtering support
Default filters
Custom filters
Runtime management
Management commands
Zero socket opener
Other extension modules
Amazon E-commerce service
Flickr service
WeatherZero forecast service
Wikipedia service
Reference
Zero command line interface
JavaDoc - Public API
JavaDoc - Public SPI
JavaDoc - All Classes

 

Resource (REST) handling

Project Zero simplifies the task of implementing RESTful resources. The following sections of this article provide information about handling REST resources:

RESTful design

RESTful designs often make use of collections. A collection is a simple model for manipulating a set of resources. Collections have member items that you can add, remove, update and delete. You can also get a list of members in the collection. For example:

HTTP Method    URI                   Description
-----------    ---                   ----------------
GET            /people               list members
POST           /people               create member
GET            /people/1             retrieve member
PUT            /people/1             update member
DELETE         /people/1             delete member

Simple convention for resources

Zero supports the collection model natively within the <apphome>/app/resources virtualized directory. Each script within the resources directory represents a resource handler, which implements the collection and member operations.

Resource handlers are accessed via a simple URL convention, based upon the following pattern:

/resources/<collection name>[/<member identifier>[/<path info>]]

For example, a request to /resources/people/1 has the collection name "people" and member identifier "1". The collection name identifies the resource handler (here, <apphome>/app/resources/people.groovy) and the value of member identifier is provided as a request parameter with name "<collection name>Id" (here, zget("/request/params/peopleId") == 1).

The resource handler is a typical Zero event handler, designed to handle resource CRUD events. HTTP methods are mapped into collection and member events according to the following:

Resource GET PUT POST DELETE
Collection list putCollection create deleteCollection
Member retrieve update postMember delete

Following is a more detailed example of request patterns and corresponding events and parsed data:

HTTP Method URI ...invokes method in app/resources/people.groovy ...with event data
GET /resources/people onList()  
POST /resources/people onCreate()  
GET /resources/people/1/accounts onRetrieve() zget("/request/params/peopleId")==1
zget("/event/pathInfo")==/accounts
PUT /resources/people/1 onUpdate() zget("/request/params/peopleId")==1
DELETE /resources/people/1 onDelete() zget("/request/params/peopleId")==1


HELP PHP Refer to Resource (REST) handling in PHP for more information on developing resource handlers using PHP.

Sample collection handler

Showing a Groovy implementation:

<apphome>/app/resources/people.groovy

 
def onList() {
    // Get configured DataManager for data access
    def data = zero.data.groovy.Manager.create('peopleDB')

    def result = data.queryArray('SELECT * FROM people')

    // Serialize list to JavaScript Object Notation format
    request.view = 'JSON'
    request.json.output = result
      
    render()
}

def onCreate() {
    // Convert entity to JSON object
    def emp = zero.json.Json.decode(request.input[])

    def data = zero.data.groovy.Manager.create('peopleDB')

    def memberId = data.insert(
                      """INSERT INTO people (firstname, lastname)
                         VALUES ($emp.firstname, $emp.lastname)""", ['id'])

    // Set a Location header with URI to the new record
    locationUri = getRequestedUri(false) + '/' + memberId
    request.headers.out.Location = locationUri
    request.status = HttpURLConnection.HTTP_NO_CONTENT
}

def onRetrieve() {
    // Member id is parsed from the path
    String id = request.params.peopleId[]

    def data = zero.data.groovy.Manager.create('peopleDB')
    def person = data.queryFirst("SELECT * FROM people WHERE id=$id")

    if(person!= null) {
        // Use ViewEngine JSON rendering
        request.view='JSON'
        request.json.output = person
     
        render()
    
    } else {
        // Error handling
        request.status = HttpURLConnection.HTTP_NOT_FOUND
        request.error.message = "username $username not found."
        request.view = 'error'
        render()
    }
}
 
def onUpdate() {
    def emp = zero.json.Json.decode(request.input[])

    def data = zero.data.groovy.Manager.create('personDB')

    data.update("UPDATE employees "
        + "SET firstname=$emp.firstname, lastname=$emp.lastname "
        + "WHERE id=$emp.id")

    request.status = HttpURLConnection.HTTP_NO_CONTENT
}
 
def onDelete() {
    def id = request.params.peopleId[]
    def data = zero.data.groovy.Manager.create('personDB')

    data.update("DELETE FROM people WHERE id=$id");

    request.status = HttpURLConnection.HTTP_NO_CONTENT
}

Nested resources

By default, resources in Zero are presumed to be flat in terms of the URL pattern. Resources can be nested by specifying the valid relationships in a bonding file associated with the resource handler. For example, the bonding file associated with employees.groovy would be employees.bnd. If the bonding file is present within the app/resources virtualized directory, then the content specifies the valid access patterns for invoking the resource.

For example, consider an example of nested resources:

/resources/people/<peopleId>/accounts/<accountsId>

Although it is possible to handle this request with the people resource handler and pathInfo, the implementation may be better factored by implementing the account resource directly as shown in the following example:

<apphome>
+ app/
  + resources/
    - people.groovy
    - accounts.groovy
    - accounts.bnd

accounts.bnd is a text file that contains one nesting pattern per line. The nesting pattern is a slash-delimited list of resource names. The hash mark (#) indicates a comment line.

Example: bonding file

# Nesting relationships for the account resource
people/accounts

When invoked as a nested resource, member ids of parent resources are provided to the target resource handler as query parameters named as <collectionName>Id. The following table provides an example.

HTTP Method URI ...invokes handler in accounts.groovy ...with event data
GET /resources/people/0/accounts onList() zget("/request/params/peopleId")==0
GET /resources/people/0/accounts/1/checking onRetrieve() zget("/event/pathInfo")==/checking
zget("/request/params/accountsId")==1
zget("/request/params/peopleId")==0

ALERT! Note that the patterns in a bonding file are the only ways to invoke that resource. In the above example, a request for /resources/accounts would result in a 404 because accounts does not appear as a pattern. To also support /resources/accounts, then the bonding file could be changed to:

# Nesting relationships for the account resource
accounts
people/accounts

Hierarchies of flat resources

Another pattern of RESTful design uses flat resources and query parameters to implement hierarchical relationships.

The example of nested resources:

/resources/people/<peopleId>/accounts/<accountsId>

could be recast with flat resources and query parameters as:

/resources/accounts/<accountsId>?people=<peopleId>

Because Zero provides member ids of parent collections as query parameters in the nested resources pattern, just as you would receive in this pattern, the handler implementation for a given resource could be identical for both patterns.

The following table provides an example of this pattern.

HTTP Method URI ...invokes method in accounts.groovy ...with event data
GET /resources/accounts?peopleId=0 onList() zget("/request/params/peopleId")==0
GET /resources/accounts/1/checking?peopleId=0 onRetrieve() zget("/event/pathInfo")==/checking
zget("/request/params/accountsId")==1
zget("/request/params/peopleId")==0

Generating and displaying REST API tables

By default, all Zero applications have the ability to display API documentation for their RESTful resources; once your Zero application is running, you can visit http://localhost:8080/resources/docs to see an index of all RESTful resources in an application and REST tables that describe the syntax and semantics of their HTTP operations. You can learn more by reading about Zero's RESTdoc tool.

r31 - 09 Feb 2008 - 04:02:37 - madhu
Syndicate this site RSS ATOM
Copyright 2007 © IBM Corporation | Privacy | Terms of Use | About this site