Here’s some random thoughts I’ve had about REST while interacting with commenters on my previous blog. Please, please, they are just thoughts, not rules of thumb I’m taking on. Some things to think about and ponder…
Use Links instead of PATCH
The idea of using the new PATCH HTTP operation makes me squeamish. I’m not sure why, but intuitively I don’t like it. Maybe its because so many semantics can be hidden behind it? Maybe its because a user is going to have to read a lot of documentation to understand how to interact with it? I think I’d rather use links instead. Let me elaborate. Consider this customer XML document:
<customer> <first-name>Bill</first-name> <last-naem>Burke</last-name> <address> <link rel="edit" href="/customers/333/address" type="application/xml"/> <street>...</street> ... </address> <billing-address> <link rel="edit" href="/customers/333/billing-address" type="application/xml"/> ... </billing-address> ... </customer>
If you were using links instead of PATCH, doing a GET on a specific customer resource returns you a document that pretty much describes to you how to interact with it. The “edit” link elements under address and billing-address let you know that you can partially edit the document without having to refer to any user documentation (or yuck, and WADL document) on whether PATCH is supported or how you use PATCH on the resource.
Apr 01, 2010 @ 14:01:40
Bill:
Your solution is one I’ve used many times and I like it for the case you show here.
However, PATCH works very well when you want to make a series of small changes to a large document and do not want to send the full set of changes. For example, sending edit comments on a chapter or article. Or modifying a few lines in a structured list (such as a list of U.S. postal codes).
An added benefit of using PATCH in the way I describe is that applications can keep a record of the patches and recall/replay them if desired.
It’s true that, in order for PATCH to work well, clients and servers need to agree on a media-type to use for the PATCH, but that support can be advertised (as a media-type) via the OPTIONS method (for servers) and the Accept header (for clients). Using a media-type reduces the documentation details since it’s the media-type itself that describes the details of how PATCH will operate on that resource. There are not many “PATCH media-types” yet, but I suspect that is just a matter of time. In the meantime, folks can use custom PATCH/DIFF media-types while we coalesce around some standards.
I’ve used this same approach many times via the POST method w/ a custom URI (e.g. /chapters/4;patch). Even now that PATCH has been approved, I still use this POST approach since it is already backed into my codebase.
Apr 01, 2010 @ 14:37:15
Opps! I should have been referring to the “Accept-Patch” header for advertising support for PATCH. It’s in RFC5789, but I missed that in my post. (http://tools.ietf.org/html/rfc5789#section-3).
Thanks to @webr3 (Nathan) for the catch.
Apr 01, 2010 @ 20:45:26
PATCh sounds interesting for what you describe (specifically the recall/replay feature), but I’m skeptical that it will be useful for the Java EE community. This is because these document-based resources usually have some kind of database behind them or some legacy pure Java API. Unless you define specific media types per patch option, so that apps can dispatch based on media type, any diff/patch format is gonna require unneeded extra processing just to figure out WTF the client is asking the server to do. I’d just rather keep things simple myself. Simple is what attracted me to REST in the first place…
Apr 01, 2010 @ 20:55:10
Bill:
I suspect you’re right. There are server frameworks that are not going to be tuned to support these types of interface operations. It’s not a storage issue, but the way in which storage and the HTTP interface are linked.
For example, I work w/ an HTTP interface that treats almost every text-based payload as XML within the HTTP middleware – no matter the advertised content type of the client’s payload (JSON, HTML, SVG, etc.) or the actual storage medium (relational DB, flat file, etc.) That makes supporting a DIFF format relatively straight forward for this HTTP middleware.
Libraries that focus on serializing the HTTP payload directly into binary objects (.NET, Java EE, JSON in javascript, etc.) will have a bit of work to do to make supporting a PATCH media-type relatively straight-forward.
Apr 01, 2010 @ 21:05:29
Eh, Mike, come to think of it, maybe my skepticism is unfounded. One feature I thought was cool about Adobe’s Flex was that its distributed updates included diffs with the object that was transmitted. Specifically, which properties had changed. So, I guess a strong diff format would be extremely helpful even for Java EE based systems. Still, I think DIFF or PATCH (the text formats) and PATCh requests with XML or JSON fragments are not something very interesting at the moment, and I’d still prefer links.
Apr 01, 2010 @ 21:13:46
I forgot about the Flex example. They worked up the middle layer to sort that out – even without “PATCH”, or course!
I’ve seen a couple JSON DIFFs and there are a handful of common XML DIFF formats. Most of my work is with a single XML-based media-type for an entire application (mimics XHTML, but no UI features, just data and link semantics). That means a single DIFF pattern works for all my payloads (including the ability shoot a DIFF from the server to a client – kinda like Flex!).
And yeah, links are always easier to deal w/ as long as you don’t have distributed caching issues (ETags solve most all of that) and the payload lends itself well (as in the composite-type example you show in your post).
Apr 01, 2010 @ 14:30:39
Accept-Patch: header pretty much covers all of this..
Apr 01, 2010 @ 14:51:59
Bill,
just as a note: I’d always emphasize the use of specific media types when talking about REST examples. In your example, there is actually nothing that tells me how to interpret the customer XML because you do not provide a media type. It would be more educating if you had make your example a response. For example:
GET /customers/22
200 Ok
Content-Type: applicaton/vnd.foo.customer
….
It would then be ‘clear’ that the specification of applicaton/vnd.foo.customer contained the processing rules, e.g. for the link element.
I’d also try to never use application/xml in examples because many people just do not understand yet, that its use introduces hidden coupling (on the expected schema). It is always better to be specific in examples (at least until the majority of people understands that you cannot be RESTful with application/xml or application/json).
See http://nordsc.com/ext/classification_of_http_based_apis.html#http-type-one
Jan
Apr 01, 2010 @ 20:29:28
Your view that application/xml and application/json as being unRESTful media types is not an idea I think you should be promoting. I understand your argument, and, I myself lean toward defining custom media types over reusing generic ones, but a lot of people disagree with our opinion.
Apr 01, 2010 @ 20:48:43
Let me rephrase. I don’t think its an idea you should represent as being *fact* and instead promote it as your own personal opinion.
Apr 02, 2010 @ 09:53:24
Bill,
that has nothing to do with opinion. It *is* a fact that the processing semantics of application/xml are only ‘handle as XML’. The only reasonable thing a dispatcher can do based on the Content-Type application/xml is to hand it to an XML parser. Anything else would mean that the dispatcher relies on out-of-band knowledge. application/xml messages cannot be self-descriptive. That is nothing to argue about.
Jan
Apr 02, 2010 @ 19:40:57
It *is* your opinion. Search rest-discuss. You’ll find multiple different long discussions on why custom media types are bad. (Not that I agree that custom media types are bad). BTW, you’ll have to link me to your interpretation of self-description. I do not find your interpretation in Roy’s thesis. Linking to your own blog doesn’t count 😉
Apr 02, 2010 @ 19:50:34
See http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven comment #31 for a more authoritative source.
BTW, just because many people prefer something it does not mean that it is correct. You said that a couple of times in this thread. Without the continuous educating work of people such as Roy and Mark Baker we would still have to use WS-DeathStar for any integration work. I for my part aim to continue that work and not follow what people deem correct due to the lack of better knowledge.
Cheers,
Jan
Apr 02, 2010 @ 22:57:26
Including the TAG if I read the following correctly:
http://www.w3.org/2001/tag/doc/selfDescribingDocuments.html#stablelayers
Apr 05, 2010 @ 11:58:12
Isn’t there always a schema that the parties have to agree on? May it be hidden or not. In this example application/vnd.foo.customer doesn’t tell me what the XML looks like unless I have a schema definition that defines it. In fact it doesn’t even tell me that it is XML that will be returned. But if I have a schema then I could just as well use application/xml.
To me this discussion sounds like “should we use enums or strings?”. Enums are more strict but they reduce the flexibility. With enums I have to change code every time I need a new value instead of just using a new value. Same here. Now I need a new content type that every client has to recognize instead of just augmenting the schema.
Frank
Apr 05, 2010 @ 13:41:25
Frank,
media types do not just define what schema(s) they use. Media types define the *processing semantics* of a message. Without stating the processing semantics, messages cannot be self descriptive – instead, their interpretation would rely on out-of-band agreement. REST ‘forbids’ such out-of-band knowledge.
Consider I send you this:
…
is that an html document? You think so?
I claim it is an XSLT document….
The only way to make the processing intention explicit is to use a content type header with my message with an explicit media type, such as application/xslt+xml
Jan
Apr 05, 2010 @ 13:42:29
Doh – here is the XML again:
<html>
…
</html>
Apr 05, 2010 @ 15:17:36
Messages can never be fully self-descriptive without the domain knowledge the API was designed for. There has to be something that the client and the server agree upon and that is not coded into every message. What you can achieve IMHO is better readability and reduced ambiguity.
If the API expects XSLT then the server needs to check whether what you are sending is really XSLT and cannot rely on the provided content type.
I can follow the reasoning being application/xml and application/json for supporting different representations of the same resource. Or for different types of XML as in your example. But why would I need to specify a custom content type for every entity I am using? The processing intention is also in the URI and in the http verb I’m using. It makes the API more complex and less readable.
Frank
Apr 05, 2010 @ 19:20:40
Frank,
you cannot *check* whether <html>…</html> is HTML or XSLT. Only the Content-Type header can tell you. The entity can look exactly the same, byte by byte.
Besides that: who says you need one media type per entity? I’d rather use one media type per domain, e.g. application/atom+xml for blogging or (a hypothetical) application/procurement+xml for shopping, fulfillment etc. Basically, the media type identifies the application (or ‘plugin’) that should handle a message. The specific XML document type (e.g. feed vs entry or catalogue vs order vs invoice) can by dispatched on *inside* that handling application. Media types map to ‘business domains’, business entities.
Jan
Apr 05, 2010 @ 19:22:33
Something is eating my words today. Last sentence should have been:
“Media types map to ‘business domains’, not business entities.”
Apr 06, 2010 @ 04:57:46
Of course I can check whether what the client is sending me is XSLT or HTML. If I have a resource which accepts both I actually have to check. You perform input validation on the server as you cannot trust that the data the client is sending. The content-type header is just another piece of information and IMHO a special content-type header is redundant and complicates testing of the API.
The only use case for special content types I can see is if you accept polymorphic input on a single resource URI.
PUT /customer/123
Content-Type: application/vnd.foo.customer
...
In this example the content type header adds no additional value to the message as the client is already PUTting the resource under
/customer
and the XML that is provided contains the<customer>
tags.However, when a tester wants to test this call he won’t necessarily remember that he has to provide the special content header instead of application/xml and IMO he shouldn’t have to.
With web services there are machines talking to other machines not humans randomly browsing the web. A web service client can never be completely generic as it is performing a specific function.
I can understand your reasoning why you would advocate for special content types for keeping things tidy. For me they just add complexity and no real benefit but they do make testing more difficult.
Frank
Apr 06, 2010 @ 05:00:11
How do you use the code tag here? A preview would help before posting.
The example should read
PUT /customer/123
Content-Type: application/vnd.foo.customer
<customer>
…
</customer>
Frank
Apr 06, 2010 @ 07:09:21
Frank, you write “Of course I can check whether what the client is sending me is XSLT or HTML.”
How do you check that?
Jan
Possible iteration on avoiding duplicates « Bill the Plumber
Apr 02, 2010 @ 22:34:02
Apr 03, 2010 @ 04:03:06
Regarding Jan’s argument – the TAG and several others disagree with the notion that custom media types solve the coupling problem. Custom media types are an impractical way to deal with custom application semantics. At the end, they leave the same kind of mess that XSDs and WSDLs left.
Apr 03, 2010 @ 08:33:43
Subbu,
the question here was not what the best way would be to handle the schema explosion problem but the RESTfulness of generic media types. Messages are not self descriptive when generic types are used and hence not RESTful.
Jan
This Week in #REST – Volume 10 (Mar 29 2010 – Apr 4 2010) « This week in REST
Apr 05, 2010 @ 07:27:05
Links « Beautiful Discovery
Apr 21, 2010 @ 23:46:10