Friday, April 17, 2009

RESTFul Web Services - HATEOAS vs URI Templates

A quick search for RESTful services leads one to documentations on how representations of resources are retrieved or manipulated. These resources are often addressed by a URI template.

Take for instance, the SocialSite API:


/people/@all [?search={searchString}]
GET - get all people

/people/{userId}/{groupId}
GET - members of a group


With all possible actions already provided and neatly written out, why then should we bother with hypermedia?

As systems evolve, so too their API. One way of supporting evolution is to version your service. The problem with this approach however, is that for every change in a URL pattern that clients have come to depend on, a whole new version is needed. This may call for untimely deprecation of the old API, or having to maintain both simultaneously.

One solution is to let clients use hypermedia as the engine of application state (HATEOS). From a known URI, discovers other resources of interest and possible actions to them. In the SocialSite example, the '/' may return something an html representation (with Web Froms 2.0) containing the snippet:


<a id="get_all_people" href="http://www.blogger.com/people">All People</a>
<form id="get_group_members" method="get" action="/people/{userId}/{groupId}">
<input name="userId" id="userId" type="text">
<input name="groupId" id="groupId" type="text">
</form>


HTML forms are designed to be use by people however. We can probably assume that actions having no arguments are mapped to 'a' elements, while those having arguments are mapped to 'form' elements. A more generic approach is to use WADL.

Another advantage of WADL is that it is easier to refer to. A WADL on a resource may either be embedded in a single element in an XML or linked to. Upon retrieving the WADL, it is easy generate a client. Forms and links on the other hand are typically scattered and each are referred individually, possibly using XPath. (Embedded WADLs, forms, and links must be placed strategically in a consistent location. Having differing locations per resource representation can cause too much coupling between the specific resource representation and the clients.)

A service's WADL document must be processed at runtime. Ideally, a service publishes the WADL document and instructions how to cache it. If the cached version expires, the client issues a conditional GET to the WADL document. Only when something has changed should the client update its defintions.

Are URI templates evil? Definitely not. It's a good way assign URIs to resources. Relying on URI templates on the client however cripples the client and freezes the service. The problem lies on the how the services direct its users to write their clients. They may have perferctly RESTful services but draw users to rely on their URI templates.

Sources
[1] http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
[2] http://weblogs.java.net/blog/mhadley/archive/2009/04/hateoas_with_wa.html