in REST

Explaining State in HATEOAS

Explaining "state" in "Hypermedia as the Engine of Application State" (HATEOAS) is a bit tricky, particularly when you have to do it under two minutes.

The problem is that, the word "state" means different things to different people. For most of us coming from some background in web development, state usually involves numbers, strings, booleans, and other objects stored in some place, say, in an in-memory session. For instance, every beginner-level book on web development includes a shopping cart style sample that stores the cart in an in-memory session. If we extend that notion to understand or explain HATEOAS, it would make us jump to the conclusion that, to make hypermedia as the engine of application state, the server will have to encode similar objects into some XML or such form of representation in response to each request. This line of thinking is a trap.

Here is why. Once the server includes such state in a representation, the next step for the client is to replay the state in future requests to the server. Then we are talking about exchanging those objects back and forth, and not every HTTP verb has enough room to carry that state. This line of thinking will then start to shoot holes into the notion of a uniform interface because, to fit the state in a request, the client may have to resort to POST. I can almost see message passing over POST as the next logical step. At this stage, whoever is trying to explain HATEOAS may have make some lame excuses and move on. Whoever is listening will then conclude that "yeah, this won't work for my apps".

Here is an example that I find most useful to explain the "state" in HATEOAS.

There are three pages in a UI. The first page has a link to go to the second page. The second page has a link to go to the previous page as well as the third page. The third has a link to the second page and another link to the first page.

A client starts from the first page, and then through the link on that page, goes to the second page. The fact that this page has one link to the first page and another to the third page implies that the current state of the application (i.e. the interactions) is that "the client is viewing the second page". That is what it means by hypermedia as the engine of application state. It does not necessarily mean serializing application state, such as "<page>2</page>" into representations.

I admit that I am simplifying this a bit. The point is that state does not necessarily mean some data stored in representations. HATEOAS means that representations reflect the current state of the app through links with known relations. Those links may contain opaque references to some persistent state on the server.

Write a Comment

Comment

11 Comments

  1. I think application state can be boiled down even further than that. The way I try to explain it is by saying that it’s where you are and how you got there. Then I’d use an example of it at work in a regular website, but that first bit (“it’s where you are and how you got there”) is the critical thing to understand; the explanation just reifies it.

  2. Although using the common example of HTML passed back with a FORM in it to describe HATEOAS is a good start, I find that it leaves people still scratching their heads. Its like trying to convince somebody Number theory is so cool by stating “1 + 1 = 2!” Its just too obvious its invisible.

    I’ve explained HATEOAS with this analogy to Java developers. Imagine, a Java Swing app passing value objects to a remote Hibernate service and merging the changes. Instead of Java objects are your value objects, think of XML or JSON. Now add the idea of embedding links into your XML or JSON that tell you where you can edit the service that represents these value objects, or links to other services related to this data.

    Maybe I’m poisoning developer minds with impure thoughts, I don’t know… :)

    • I don’t want to say that this is “poisoning developer minds”, but explaining that representations are akin to some value objects is a bit misleading. Here is why.

      Let me consider a bank transfer example, where we identified a bank transfer as a resource. The usual flow is as follows:

      POST /transfer —–> 201 Created, Location: http://example.org/transfer/1

      Now, when a client submits a “GET /transfer/1″, what should the server return? In the value object model, it would return some serialized form of that object, e.g., as in

      <transfer>
      <id>urn:example:transfer:1</id>
      <link rel=”src” href=”…”/>
      <link rel=”target” href=”…”/>
      <amount>100</amount>
      </transfer>

      But this does not tell me anything about the “state of the application” viz., the “state of the interactions between the server and this client”. The state of the application could be that the transfer is pending, and the client will need to check some other link to get the status of the transfer. This could be represented by including a link to that status resource in the above representation. At the end, we have links, but IMO, what they are meant to represent is a key point.

      Consider a different example. A client is submitting a POST to create a new customer resource. Due to some peculiar implementation details, the server wants the user to verify this process by submitting a one-time verification link.

      201 Created
      Location: http://blah

      <customer>

      <link rel=”verify” href=”http://blah?adasd312da”/>
      </customer>

      The link here indicates the state of the application, i.e, the process is not done, and the user needs to activate the link with relation “verify”.

      To sum up, representations contain both the (persistent) state of the resource as well as the state of the application (i.e., the interactions).

  3. IMO, the topic of “state” is very important. Would be nice if you could write another post “Explaining State in REST” (here I mean the third letter “S” in the acronym) and comparing it with the State in HATEOS.

  4. @Bill, @Subbu

    I am wondering how about embedding only the URI of a resource (rather than its representation) into the referring resource representation.

    This may lead to additional round-trip (fortunately GET can be cached), but it will let you avoid “stateful-ness” of the resource by the introduced level of indirection.

  • Related Content by Tag