BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Implementing Partial Updates In RESTful Services

Implementing Partial Updates In RESTful Services

This item in japanese

Bookmarks

Recently Alex Scordellis posted an article on how the interaction of a client and a RESTFul service can be modeled and designed  for updating partial resources. 

[In the book REST In Practice, by Ian Robinson, Jim Webber and Savas Parastatidis] there was one concept I found puzzling. the authors recommend using POST to update the state of a resource. This is driven by a choice of interpretation of the semantics of PUT. According to the HTTP spec:
If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server.

In the book, the authors interpret this to mean that the body enclosed with the PUT request should contain the same elements as the representation served by GET requests at the same URI. Since we are using the HATEOAS style, representations include links and other hypermedia controls. The implication is therefore that clients should PUT representations containing both business data (for example the new contents of the coffee order) and hypermedia controls (the available next steps in the workflow).

Alex is of the opinion that the hypermedia and resource representations from the services should drive the workflow of the clients and he suggests four possible ways to model this interaction. Some of these examples harks back to the article on RESTBucks.

Use PATCH
[…] it's not widely supported. It also feels semantically wrong to me. From the client's point of view, the business data comprising an order (how many lattes?) is the whole resource. The client doesn't see this as a PATCH, but as a replacement, i.e. a PUT. PATCH might make sense to express concepts like "use skimmed milk in the latte, instead of the full fat I originally ordered".
Use POST
This is the approach suggested in the book. For me, it has similar drawbacks to PATCH. POST implies appending to a resource. POSTing one cappuccino to a coffee order resource feels like it should add one cappuccino, not replace the existing set of ordered coffees with one cappuccino.
Use PUT, including hypermedia
To follow the strict interpretation that PUT should include entire representations, the client sends both the entire new coffee order and whatever hypermedia controls the service last sent it. 
Use PUT, don't include hypermedia
The client sends a complete representation of the new order, but no links. To me, this feels conceptually right. The client fulfils the expectations of PUT by sending a complete representation of the parts of the data for which it is responsible, but does not pretend to be responsible for determining what hypermedia controls are available.

After discussions with @serialseb, @iansrobinson and @jimwebber; Alex concludes the following rule of thumb, which, also satisfies the semantic expectation from the PUT verb.

In response to GET requests, services serve complete representation of the current known state, including business data and available hypermedia controls. Clients PUT complete representations of the parts for which they are responsible.

William Vambenepe adds additional considerations to this discussion

Let’s pick a simple example. What does it mean if an element is not present in a partial update? Is it an explicit omission, intended to represent the need to remove this element in the representation? Or does it mean “don’t change its current value”. If the latter, then how do I do removal? Do I need partial DELETE like I have partial PUT? Hopefully not, but then I have to have a mechanism to remove elements as part of a PUT. Empty value? That doesn’t necessarily mean the same thing as an absent element. Nil value? And how do I handle this with JSON?

He asserts that the problem of designing the partial resource update interaction is a hard problem and has already been attempted to be solved via specifications such as WSDM, WS-Management and WS-ResourceTransfer.

The good news is that we’ve made a lot of the mistakes already and we’ve learned some lessons (see this technical rant, this post-mortem or this experiment). The bad news is that there are plenty of new mistakes waiting to be made.

Stu Charlton also weighs in on the problem and blames the fact that RESTFul hypermedia cannot really describe a data-model. According to him the two things that RESTful services need for better interoperability are

(a) a [closed] data model that covers 80% of common use cases and can be formatted with JSON and XML.

(b) a media type that covers 80% of common use cases to describe a resource's lifecycle and state transitions -- in other words, to make POSTs self-descriptive in hypermedia. Because the world of computing isn't just about updating data, it's about abstractions.

In the comments to Alex’s post Duncan Cragg weighs in with a practical solution.

You should have /two/ resources: a client order telling the server what /it/ wants, and a server "ticket" that confirms the details back to the client - and adds whatever extra data, links, etc, it wants. The server's ticket has a dependency on that client order, /plus/ on any internal or external process state it's privy to in the execution of the order. But who hosts the client order? Why, the client of course! Well, unless you have an asymmetric set-up, in which case the client can POST and/or PUT its order somewhere on the server. Now the client submits and changes the /whole/ order resource in one go, without worrying about any server-generated bits.

There have been many proposals to solving this problem; and it appears that it is easily solved if we model the resources appropriately. Often times just thinking of resources as entities that support CRUD is the problem and modeling resources as “resources” and the services they offer as in Duncan Craggs example is the solution. The larger problem however is how to get everybody to agree on the solution. Be sure to check out the original posts and the comments and share your opinions on this forum as well.

Rate this Article

Adoption
Style

BT