Friday, June 22, 2012

IANA and the Last Layer of REST's "Uniform Interface"


[Before you read any further, go and read Martin Fowler's simple description of Leonard Richardson's REST Maturity Model. What I'm writing about here will make a lot more sense after that. Trust me.]

One of the things I've liked about REST as compared to SOAP (other than the fact that SOAP-based Web Services introduce fresh dependencies in the form of schema and WSDL files, negating the dependency-reducing spirit of SOA) is that REST standardises vocabulary, allowing designers to construct solutions out of standard terminological "components" rather than having to invent their own.

For example, instead of the arbitrarily-named and "open set" of SOAP verbs CreateQuote, SubmitQuote, SearchOrders, AmendOrder, CancelOrder, AddItem, RemoveItem, etc., one merely creates resources like Quote, Order and Item (and others for convenience) and applies a "closed set" of standard verbs to them (GET, PUT, POST and DELETE).

This much has been clear, and I like this. But I confess I have never fully understood how exactly REST manages to shift the coordination model away from centralised orchestration (à la WS-BPEL) to one of decentralised choreography (which is what the HatEoAS principle is all about).

Yes, the server provides a context-dependent, constrained set of links with each response, and the client is forced to follow one of these links, and is therefore shepherded in certain well-defined directions so that a business process completes in a well-defined way. [In the past, I've even referred to HatEoAS as "Hypermedia as the Envelope (not the Engine) of Application State" in recognition of its function as a set of constraints rather than an active driver.] This is choreography all right, where it takes two to tango, rather than orchestration, where services march to a single drum (pardon the discordant musical references). What I didn't understand was how these links could be made intelligible to an automated client that wasn't primed to understand them a priori.

A link looks like this:
<link rel="logical-action" uri="/some-resource"/>
I didn't understand how the descriptive "logical-action" in the link relation above was made meaningful to the client. After all, URIs are meant to be opaque in the sense that clients are not expected to understand their internal patterns and "hack" them to make future requests. Clients need to be guided purely by link relations (the "rel" attribute).

This finally became clear to me yesterday when I attended Jim Webber's excellent full-day tutorial on REST at QCon New York. [Attendees at Jim's talks can be assured of three things: (1) an unending spate of wry Brit jokes, here mainly directed at the Yanks ("tax dodgers who drive on the wrong side of the road"), (2) lots of Doctor Who references, and (3) some absolutely top-class technical insight and instruction.]

Much as I enjoyed the Brit humour (even as some of it came at the expense of Australians ("convicts who speak degenerate English")) and the Doctor Who references, I think the major value for me from this talk was the clarification that link relations are standardised too! I learnt that IANA has published a standard list of link relations that servers can use to describe the "next steps" that a client can perform, and since these are by definition "well-understood" descriptions, clients do not need prior negotiation with the server to learn what they mean!

The last piece of the jigsaw puzzle has now fallen into place in my head.

Some of the most important IANA-defined links, in my opinion, are:

  • "first", "last", "next" and "prev" (alias "previous"): useful for chunked navigation of lists
  • "self", "up", "start", "index", "contents", "glossary", "appendix": useful for orientation, repositioning and meta-information about the content itself
  • "item" and "collection": useful to navigate master-detail relationships in both directions
  • "alternate", "duplicate", "canonical", "current": helpful to refine the ability to link to a resource more accurately
  • "edit" and "edit-media": suggest how to change content
  • "help": needs no explanation
  • "search", "tag": useful for research and taxonomy
  • "working-copy", "working-copy-of", "version-history", "successor-version", "predecessor-version": helpful when editing documents collaboratively
  • "payment": extremely useful in e-commerce applications by providing a standardised label to nudge customers towards the checkout

[If an application requires link relations that are more specialised, then they need to be namespaced, e.g., "mycorp:specialised-function", with the term before the colon being the namespace. The client will have to understand terms in the specialised namespace of course, but that's only reasonable.]

I prefer the more verbose form of the link tag, which looks like this:
<link rel="mycorp:apply" uri="/applications" method="POST" 
         type="application/vnd.mycorp-application-v1_1+xml"/>
Now the client also knows what HTTP method to use, and what schema the submitted document should conform to.

I can now see that REST has done a lot to standardise the development of applications in a SOA-compliant way. My last major query about how REST communicates with clients to bring about choreographed processes has now been answered.

This is great stuff. Thanks once again to Jim Webber for a very instructive tutorial! I guess we have a more powerful weapon than Torchwood now, Jim :-).

No comments: