Using Atom with the RESTful API in R2 of SWDP

The RESTful API in R2 of SWDP has an example of how to use Atom (more purcolation) in a sort of Atom publication protocol manner (i.e. it is not fully conforming to the specification).

The following table presents the URI templates, the Java classes that map to those templates and the HTTP methods supported by those Java classes;

URI template Java class HTTP methods
/service ServiceResource GET
/collection/ FeedResource GET, POST
/collection/{entry} EntryResource GET
/collection/{entry}/media EntryResource GET
/collection/edit/{entry} EditEntryResource PUT, DELETE
/collection/edit/{entry}/media EditEntryResource PUT

I am somewhat embarrassed by the implementation! (it was hacked together rather quickly) but the example is instructive of how easy it is to get something functional working with Atom and how the API features are utilized (how Java classes relate to the URI path hierarchy and inheritance of HTTP methods). The application supports the create, read, update and delete of Atom entires and Atom media entires.

The FeedResource class, that corresponds to the Atom collection resource, is declared as follows:

@UriTemplate("/collection/")
@ProduceMime("application/atom+xml")
@SubResources({EntryResource.class, EditEntryResource.class})
public class FeedResource {

The UriTemplate annotation declares that the URI template of the Atom feed is an absolute URI of "/collection". The ProduceMime annotation declares that, by default, all HTTP methods implemented by the FeedResource class will produce content of the MIME media type "application/atom+xml". The SubResources annotation statically declares Java classes that are subordinate resources of the collection resource, which essentially means that the URI templates declared on the subordinate Java classes are relative to the URI template of the FeedResource class (but only when referenced in the context of the collection resource as those Java classes could be referenced as subordinate resources in other contexts).

The EntryResource class, that corresponds to the read-only Atom entry resource, is declared as follows:

@UriTemplate("{entry}")
@ConsumeMime("application/atom+xml")
@ProduceMime("application/atom+xml")
public class EntryResource {

The UriTemplate annotation declares that URI template of the Atom entry is a template variable "{entry}" and when this class is referenced from the FeedResource class the absolute URI template of this resource will be "/collection/{entry}". (The value of the {entry} will be a UUID, which corresponds to that in the atom:id element.) The ProduceMime and ConsumeMime annotations declare that, by default, all HTTP methods implemented by the EntryResource class will produce and consume content of the MIME media type "application/atom+xml".

The EntryResource also supports access to the media of the entry if that entry corresponds to an Atom media entry. The media is a subordinate resource of the entry and is implemented by the following Java method (on EntryResource):

@HttpMethod
@UriTemplate("media")
@ProduceMime("\*/\*")
public Representation<InputStream> getMedia(@UriParam("entry") String entryId) {

The UriTemplate annotation declares a subordinate resource relative to that of the entry resource (so the absolute URI template would be "/collection/{entry}/media"). The ProduceMime annotation overrides that declared on the class and states the method may produce any MIME media type (since the client can choose the type of media that may be published). The HttpMethod annotation declares this to be an Java method that is capable of processing an HTTP request for the HTTP GET method. This is a good example of how a Java class can encapsulate one or more resources that are closely related.

The EditEntryResource class, that corresponds to the read-write Atom entry resource, is declared as follows:

@UriTemplate("edit/{entry}")
@ConsumeMime("application/atom+xml")
@ProduceMime("application/atom+xml")
public class EditEntryResource extends EntryResource {

Notice that EditEntryResource inherits from EntryResource and thus inherits the read-only HTTP methods for the entry and media resources. The UriTemplate annotation overrides that declared on EntryResource and declares a different URI for editing an entry (so the absolute URI template would be "/collection/edit/{entry}"). It is common for some APP implementations to provide different URIs for editing Atom entries. The subordinate media resource implemented by EntryResource.getMedia method will be relative to the overridden URI template. The ConsumeMime and ProduceMime annotations are actually unnecessary since these can be inherited as well so the class could be declared as follows:

@UriTemplate("edit/{entry}")
public class EditEntryResource extends EntryResource {

The EditEntryResource supports the update to the media of the entry as follows:

@HttpMethod
@UriTemplate("media")
@ConsumeMime("\*/\*")
public void putMedia(@UriParam("entry") String entryId,
Entity<byte[]> update) {

Hopefully the annotations on the method should be self-explanatory by now :-) and hopefully you can see how to construct a set of Java classes that map to a URI path hierarchy.

The Google GData API supports optimistic concurrency of Atom entries by encapsulating a version ID in the URI. Thus we could change the implementation of EditEntryResource to be as follows:

@UriTemplate("edit/{version}/{entry}")
public class EditEntryResource extends EntryResource {

so that a "{version}" template variable is included. Of course the method parameters would need to change to obtain the version and it starts to affect the implementation of the EntryResource, not good! However, there are ways to avoid such problems while retaining good encapsulation and DRYness by using dynamic resources and class constructors. Hopefully the lessons learned from building such applications and how to improve on them will feed back into JSR-311.

Comments:

[Trackback] Nice layout of a RESTful API in table form and how it's implemented in R2 of the SWDP.

Posted by RESTful at coRank on May 29, 2007 at 02:10 PM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

sandoz

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today