Resource API refactoring
Requirements
Enhancement request
- [I143] Support asynchronous processing
- [I221] Improve parameter validation
- [I234] Support ActiveResource
- [I302] Support client-side Resources
- [I303] Faciliate Resource to Representation mapping
- [I335] Consider stateless resources
- [I346] Add minimal support for WebDAV in Directory
- [I384] Reconsider usage of interfaces
- [I462] Support generic variants in content negotiation algorithm
- [I531] Add support for Resource features
- [I625] Support PATCH method
- [I713] Support bean binding and validation
Related discussions
- [D01] 2006/11/21 - Resource as an interface
- [D02] 2006/12/28 - Handling multiple representations of a resource
- [D03] 2007/03/05 - Mapping domain objects to resources
- [D04] 2007/11/16 - Resource convention over configuration
- [D05] 2008/07/24 - Injecting Restlet resources with Guice
- [D06] 2008/07/30 - Returning multiple representations of a resource
- [D07] 2008/09/25 - Using OPTIONS to describe a Resource
- [D08] 2008/09/28 - On a Resource, when and by what is getRepresentation() called?
- [D09] 2008/10/02 - On the use of adding Variants to a Resource
- [D10] 2008/12/19 - Getting Restlet resources injected with Guice
- [D11] 2009/01/06 - Application and Resource lifecycle
- [D12] 2009/01/13 - Media type adaptor
- [D13] 2009/01/15 - Returning data after PUT/POST
- [D14] 2009/01/21 - Auto-Attachment of Resources to Router
References
- Restlet API 1.1 (org.restlet.resource package)
- JAX-RS API
- RESTEasy Client API
- Jersey Client API
- Pluggable types with JAX-RS and Jersey
Analysis
Synthesis
- Client-side resources
- Server-side resources
- Dispatching of uniform method to matching Java method
- Extension methods (WebDAV, PATCH, etc.)
- Detection of available variants
- Dispatching to representation producing method based on selected variant
- Mapping between ResourceException and reponse status
- Automatic conversion between representations and objects (beans/pojos, common technical classes such as a DOM Document)
- Automatic validation of representations received
- Automatic validation of parameters received
- Client-side Restlet post-processing (eg. filters, routers, pre-authentication, cookie management, etc.)
- Server-side Restlet pre-processing (eg. filters, routers)
- WADL resources (client and server side)
- Atom resources (client and server side)
- RoR active resources (client and server side)
- .Net data services resources (client and server side)
- Database resources
- Support IoC frameworks (Spring and Guice)
- Support GWT
- Automatic convertion between XML and JSON (via converters)
- Support the separation of composite representations into multiple method parameters
Design
- Unified API in Restlet 2.0 between Restlet 1.1 Resource class and JAX-RS 1.0 annotations to provide the best of both worlds
- Use subclassing for resources foundation
- Limited use of annotations to simplify variants declaration and method dispatching
- Each resource should be able to optionally wrap another resource (for WADL enrichment for example)
- Think about using additional annotations in the WADL extension to describe a resource (either JAX-RS API or Restlet API resources)
- Use an internal "org.restlet.engine.Method" annotation to annotate actual annotations (such as org.restlet.resource.Get) in order to declare the method name and allow easy creation of extension methods.
- Replaced the Resource#allow*() methods by leveraging the new Security API (granular authorization).
- Use more flexible variants declaration mechanism using a Map<Method, Object> where objects can be instances of Variant, Dimension, MediaType, etc.
Architecture

Class diagram
Here is a tentative class design:

Annotations
We could also define a set of method level annotations:
|
Annotation |
Description |
|---|---|
|
Delete |
Annotate methods that remove resources. |
|
Get |
Annotate methods that represent a variant of a resource |
|
Options |
Annotate methods that accept representations. |
|
Post |
Annotate methods that accept representations. |
|
Put |
Annotate methods that store representations. |
Annotations parameter
All annotation have a single optional parameter. Its name is the default "value" name allowing a compact annotation syntax.
Here is the grammar for this parameter:
CHARACTER = 'a-z' | 'A-Z' | '0-9'
EXTENSION = CHARACTER [CHARACTER]*
SEPARATOR = '+' | '|' | '*' | '(' | ')'
TOKEN = EXTENSION | SEPARATOR
VARIANT = TOKEN [TOKEN]*
INPUT = VARIANT
OUTPUT = VARIANT
ANNOTATION = INPUT [',' INPUT]* [':' OUTPUT]
Here are some valid values:
@Get("xml") : Returns a representation in the "text/xml" media type
String toString();
@Put("xml") : Stores representations in the "text/xml" media type after conversion to a DOM document
void store(Document doc)
@Put("xml:txt") : Stores representations in the "text/xml" media type after conversion to a DOM document and returns a plain text response
String store(Document doc)
[To be continued and detailled]
In order to validate the value of the annotations an annotation processor will be developped, checking the syntax of the value and the fact that it matches registered metadata extensions.
Sample code
Here is how a sample resource would look like with the refactored API. Note that both extension names and full MIME type would be supported. Extensions can be updated via the MetadataService.
import java.io.InputStream;
import org.restlet.ext.atom.Feed;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.Put;
import org.restlet.resource.Representation;
import org.restlet.resource.ServerResource;
import org.w3c.dom.Document;
public class TestResource extends ServerResource {
@Get
public Feed toAtom() {
// ...
return null;
}
@Get("xml")
public Representation toXml() {
// ...
return null;
}
@Post("xml")
public Representation accept(Document entity) {
// ...
return null;
}
@Put("atom")
public void storeAtom(Feed feed) {
// ...
}
@Put("cust")
public void storeXml(InputStream stream) {
// ...
}
@Delete
public void removeAll() {
// ...
}
}
What is nice is that we would keep the high-level terminology that we have in Restlet 1.1 (accept, store, etc.) but make it available in a more flexible and declarative way. The new ServerResource would only have lower-level methods, but with a more flexible signature than in Restlet 1.1:
- void handle()
- get() : Representation
- get(Variant) : Representation
- head() : Representation
- options() : Representation
- options(Variant) : Representation
- post(Representation) : Representation
- put(Representation) : Representation
- delete() : Representation
Implementation
- Leverage the dynamic proxy feature in Java SE
- New resource package


There are no comments.