subbu.org

On Linking - Part 1

with 19 comments

Linking is the most under-utilized aspects in modern RESTful apps. Without linking, what we are building today are essentially POXy REST apps. I categorize a well-designed POXy REST app as one that is built as follows:

  1. Models resources at the right granularity such that it can constrain the set of operations to a uniform interface.
  2. Lets clients use the uniform interface in the manner defined by HTTP 1.1, i.e., uses GET for safe and idempotent read-only operations, PUT to update resources, DELETE to delete resources, and POST to create new sub-ordinate resources.
  3. Uses media types such as application/xml or
    application/json (should I call this POJO REST instead?) to represent data.
  4. Uses representations, content negotiation, and conditional requests - i.e. it takes full advantage of HTTP as an application protocol.

This is definitely a desirable evolution from the early Flickr-style REST, which can best be characterized as follows:

  • Use URIs to identify mostly operations, but not necessarily to name resources.
  • Treat HTTP as a transport protocol, offering SOAP, XML-RPC, serialized objects etc along side REST as an interface.

HTTP as a transport protocol to POXy REST

As Tim Bray recently commented, "there are a whole lot of benefits to just getting HTTP right". Right! The evolution of apps from "using HTTP as a transport protocol" to "using HTTP's uniform interface as an application protocol" is great. Now, apps can begin to take advantage of HTTP and the infrastructure (such as caches and proxies) that comes with it for free. But there is one particular item missing from the above list.

  1. Encodes the application state and possible state transitions in representations.

Or, more abstractly,

  1. Honors the "Hypermedia as the engine of application state" (a.k.a. HATEOAS) constraint.

Both these sentences are, as some would say, "dense". Allow me to dissect this further.

A POXy REST app usually compensates for this missing piece with the following:

  1. Provide documentation containing list of all URIs and possible HTTP verbs that the clients will need to construct. This usually includes the list of query/matrix parameters for each of those URIs, and what each of those parameters mean for each URI among other things.
  2. Implement the uniform interface for these URIs in a context-free and state-free manner, so that a client app can generally submit a request to a URI at any time. Here I am using the word "context" to mean the current state of interactions, a.k.a., the application state.

Take a look at Flickr, or SimpleDB, or Twitter to find the same pattern from being repeated. If I were a client developer, each of these APIs would require that I learn when to use what URI, and how to construct each URI based on user documentation. If I were a server-side developer, this model would require me to pre-publish all possible URIs, also documenting the state under which each URI could be used. More importantly, this model won’t let the server tweak or tune URIs to be state-specific, or change URIs ever.

If the user-facing web were to work like POXy REST, web pages would just contain some presentation but without links or forms. The browser would somehow figure out the related resources such as stylesheets, images and scripts and download them along with each page. Instead of clicking links on web pages, we would be running through bookmarks or some centralized list of URIs to navigate (it won’t be navigation) the web, always consulting some documentation or cheatsheets to learn what URI to visit next. That’s just for the read-only web. I can’t even imagine dynamic web sites working like this.

If these apps were to use context-sensitive links and encode state in representations (which is the essence of HATEOAS), each of these apps would look quite different. Instead of publishing all URIs, the server would publish a few starting point URIs from which a client app would begin to navigate the app.

Linking for interactions

This results in some desirable consequences:

  • Server apps will publish a few starting point URIs, but not all possible URIs.
  • Clients will receive new URIs through links contained in representations, and use those links to make transitions that are meaningful for the current state of the app.
  • URIs remain opaque to clients, i.e., clients don’t need to learn about URIs. They may need to understand a few parts of the URIs, e.g., replaceable tokens in a URI template or adding a few query parameters. This leaves opportunities for the server to encode/rewrite URIs to suit the context.
  • Servers can introduce new resources and URIs in a compatible way through new links, potentially avoiding the versioning mess.

This style of application flow is not new. We use this pattern for almost everything on the web, as well as most flow-centric client-server apps.

Ignoring linking linking and hypermedia in general would make us invent some complex solutions and possibly limit the possible use cases that RESTful apps can support. Here are few things that I can think of:

  • Process flows: As the URIs are context free, and representations contain data but no context (i.e. application state), it becomes difficult to implement process flows. Process flows are typical of many enterprise apps, and as it stands now, POXy REST can’t completely tackle such server-to-server interactions. Once you start including application state and links within representations, it becomes easier to imagine how to model process flows RESTfully.
  • Over-emphasis on clean URIs: In a true REST app, the only requirement on URI design is to identify resources uniquely. Since POXy REST apps need to document URIs, it becomes necessary to keep them transparent, clean, and human-readable. This is nice but not required. URIs can be clean, readable and yet be opaque at the same time.
  • Over-emphasis on stateless clients and servers: As far as HTTP is concerned, the goal is to keep the interactions stateless so that interactions remain transparent to intermediaries along the network. Once the application state is captured within representations, servers can become (transient or in-memory) stateless. Whether a client becomes stateless or not depends on the nature of the app.
  • Quest for a description language: Since POXy REST apps need to advertise URIs before clients can begin to write code, we face with a need for ways to formally describe URIs, applicable HTTP verbs, and media types. See Part 2 of this post for some more discussion.
  • Higher surface area and coupling: Finally, this leads to a higher surface area due to the transparent nature of URIs, and coupling due to the need for the client to understand when to use what URI and how.

One litmus test to determine whether an app falls into this category or not is to look at the representations. If the representations contain just data (note "to represent data" in item 3 above), then it is very likely that the app is following the POXy REST model. If you see links, it probably is not.

Linked applications

Sadly, linking is also absent from development APIs and frameworks. Take JSR-311, for example. It lets me deal with URI parsing, dispatching HTTP verbs to code, constructing and parsing representations, but does not model linking and hypermedia. Linking is absent from most client APIs as well. If I am writing a client app that needs to take advantage of hypermedia, I got a lot of work to do on my own such as discovering links, following links to make state changes etc.

OK. So, the hypermedia centric model has been working well for the user-facing web (i.e. with HTML representations and browsers as client apps), but will it work for non-user-facing apps? Not so surprisingly, Damien Kantz recently concluded that "The web is built on REST. Therefore REST is good" Bullshit. But I don’t think he went far enough before coming to that conclusion. Along the same lines, the same goes for Tim Bray’s comment that "I’ll be honest: I’m not sure." about HATEOAS.

Continue to read Part 2 of this post.

  • Digg
  • del.icio.us
  • Google

September 28th, 2008 at 1:57 am

Tagged with ,

RSS feed | Trackback URI

19 Comments »

Comment by Mike Amundsen at 2008-09-28 08:59:02

I would argue that (X)HTML already has this working since it offers the <a> (anchor) tag and the form tag. Therefore it would seem this discussion is aimed at JSON and XML-based formats and how to implement anchors (links) and forms (submit blocks).

Also, the secondary discussion would be how to build generic clients that understand the links and submit blocks properly. Again, (X)HTML has this working quite well.

Comment by subbu at 2008-09-28 09:07:29

Actually - the point is not about implementing anchors and forms a la HTML/XHTML. That would be a stretch, IMO. It is about using runtime linking specific to the state of the app, as opposed to prepublished URIs.

 
 
Comment by Mike Amundsen at 2008-09-28 09:15:18

I see. This is about ‘templating’ links instead of hard-wiring them.

 
Comment by vano at 2008-10-05 13:35:09

I didn’t really get the direction of arrows in the second picture. Didn’t you mean to show that representations with possible transitions are going from the server to the client (and not vice versa) or am I missing something?

Comment by Subbu Allamaraju at 2008-10-05 15:45:57

Thanks. Removed extraneous arrows on the client side.

 
 
Comment by vano at 2008-10-06 10:12:00

Well, actually that’s not what I meant. On that figure the text “Representation with new state and possible transition” goes with the arrow directed from the client to the server. Shouldn’t those arrows go from the server to the client? Client follows links (by sending request to the server). And server returns representation (which is a response to client’s request). Kind of request/response interaction diagram.

Comment by subbu at 2008-10-06 20:33:15

Ah. Thanks for pointing it out. My eyes were a bit slow in catching that.

 
 
Comment by vano at 2008-10-06 10:23:09

And now about “transition” arrows. Probably those can be interpreted in different ways. But I think what is important to show on this diagram is that application state transitions happen on the client side. Server is stateless and doesn’t store client’s state. For each request (independently from previous ones) it provides representations with links which client follows and thus moves from state to state. So, I would put those arrows on the left side of the interaction.

Comment by subbu at 2008-10-06 21:19:52

Actually, transitions may be happening on both sides. From the client’s POV, the state of the conversation is changing, while the state of the resources may be changing on the server side as a result of the conversations.

 
 
Comment by Bill Burke at 2008-10-06 15:32:37 Subscribed to comments via email

No, JAX-RS doesn’t help much with linking/HATEOAS. I’m not sure what it can do here as is not linking/HATEOAS more embedded within the data format and thus mainly an application construct? It would be cool to get some ideas on what tools JAX-RS and JAX-RS implementations could provide to make applications leveraging HATEOAS easier to write.

 
Comment by Bill Burke at 2008-10-06 16:33:46 Subscribed to comments via email

BTW, I was thinking of extending JAXB with annotations so that you could easily embed links within it. Combined with relative URI knowledge that’s available within the JAX-RS implementation runtime, this could easily be done in a portable manner. Is there anything else you could think of?

Comment by subbu at 2008-10-07 08:03:05

That would be nice. It would also be interesting to see the programming needs of client applications. HttpURLConnection is not very useful for day to day client app development. JAX-RS has focused so far on the server side, and probably, the heads be at Sun would argue that their sole focus is server side framework, but someone in the JSE/JEE umbrella needs to tackle that problem. It would be great if there is an API on the client that supports conneg, link traversal based on relations, essentially mirroring some of the concepts from the server side.

 
 
Name (required)
E-mail (required - never shown publicly)
URI
Your Comment (smaller size | larger size)
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> in your comment.

Trackback responses to this post