« Workshop on RESTful Design 2012 (WS-REST 2012): Call for Papers | Main | Resource Profiles »

Wednesday, December 07, 2011

Comments

Feed You can follow this conversation by subscribing to the comment feed for this post.

Stefan Tilkov

Let me address your points in reverse order:

3. This could be easily alleviated by including a link in the order's representation (something like link rel='payment'), so it's orthogonal to the other aspects.
2. The reason many people don't use a state change on the parent resource is that they'd need a partial update.
1. I agree this is often a better option, and I share many of your concerns regarding action URIs. Personally, I use this pattern only if they feel natural, i. e. I can convince myself that there is other something that deserves to be its own resource, and naturally should be hierarchically “under” the parent resource. A key indicator to me is that I can find a reason to do a GET on this resource, too.

Duncan-cragg

I personally believe that this pattern, that I call 'link-rel-action', is really just RPC - the verbiness of the URL gives that away! Plus I also agree with Stefan, that a good rule of thumb is to ask what you can GET from such URLs.

There's a wonderful chapter in that excellent book .. what's it called? Ah yes, "REST: From Research to Practice" .. there's a chapter in there about a REST pattern or model called "FOREST"*, which itself talks about orders and payments and so on.. :-)

In FOREST, the author, Duncan Cragg, suggests POSTing Payment objects directly to their corresponding Ticket objects, where a Ticket is a server-side representation of a client's submitted Order. Like those slips you get in restaurants.

Further, you know when you can pay because of the state of the Ticket, no link-rel necessary (it would always point to the Ticket anyway!)

In fact, he also suggests a more peer-to-peer approach, POSTing updates on these Orders to these Tickets - containing new links to Payments hosted 'client side', which a Ticket object can GET from the client at its leisure.

Cheers!

* http://www.springerlink.com/content/v454gmw41411m061/

Duncan

dret

duncan, it's quite a conincidence that i have a couple of copies of this book just laying around... it's of course nice to see somebody reasoning very similar to the thoughts i was having, but let me step back a little. you identify the "verbiness of the URI" to be a bad sign, and i think that's my main concern, too. subbu in his cookbook in recipe 2.6, on he other hand, explicitly recommends to use "Controller Resources", and his main objection about the approach of POSTing to the URI of the actual resource is that then the POST request body would contain the verb, so he claims that the "verbiness of the representation" is a bad thing. i guess in the end the verb needs to go somewhere, since the operation is not directly part of the uniform interface, and REST only has so many places where you can stick it.

personally, to me it seems that sending such a request as a self-describing representation in a request is the cleaner way to go, because you are interacting with the resource (or, as suggested, maybe with a more generic payment resource that would allow payment for a variety of things, all of which would be linked). but for being self-describing, the payment definitely would need to have a link to the order being paid. but apart from the design option of decoupling the payment resource from the paid items, i am having a hard time coming up with actual reasons to go one way or the other. it just seems more natural to represent the operation in a self-describing message, in the same way as you would have filled out a form to initiate an action on a pending business process in old-school paper-driven processes, and there the interaction point would have been the pending business process, and not an endpoint specifically created for this one possible action. but still, this is mostly a gut feeling, but maybe that's all there is in this case.

one last remark: you say "you know when you can pay because of the state of the Ticket, no link-rel necessary (it would always point to the Ticket anyway!)", but i don't quite get that. how do you represent the state and detect the fact that it's ready to accept payment? isn't one of the fundamental principles of REST that such a state change should be driven by hypermedia controls, and thus a state change would be exposed as a link a client can follow? that was my assumption, but it seems that you have something else in mind. how do you represent the state change in the resource?

dret

stefan, thanks for the comment. i think what you're saying in point 3 is what i was suggesting, so we're in agreement. about point 2 i am wondering whether the desire to make a partial update is the main issue here. you can make partial updates by POST or PATCH (which is what i am suggesting), but more importantly, you're not really "updating" the resource, at least that's not my understanding of the semantics. you're transferring information to the resource that will cause it to change state, and that information should be self-describing. it's like turning in a payment stub in a restaurant. maybe you pay with your waiter (he may be the "order-specific payment point") or with the check-out guy (who will need a link to the order to make sense of your request to pay), but in both cases you're initiating a state change that, should it succeed, will change your order to change state. essentially, the payment processor then will update your order state from "open" to "paid", but that's not what you do as the one initiating the payment.

and i think that's pretty much my response to your point 1, too. payment and a paid order are different things, and may even be managed by different authorities. if they do, there should be a payment resource somewhere that accepts payments that link to orders. but should you decide to combine payment and order management into the same authority, then payment becomes just a new interaction that is supported on an order, and as a result will, if it is accepted, change the state of the order itself. i don't think that the action URIs often allow GET, but i may be wrong.

mamund

in cases where we expect the client to recognize, parse, and activate" state transitions, they will need to be labeled consistently. designs can do this in various ways: [create-customer href="..." /], [form class="create-customer" action="..." /], {"create-customer" : {"href=" : "...", ... }}, etc.

these are all examples of "affordances" in the response; they "afford" the ability to create a customer. in my experience, it is much preferred to include self-describing affordances in the response rather than only a URI.

Pedro Félix

Assuming that an order payment is desirably an idempotent operation, using a resource specific payment URI ("http://example.com/order/42/payment"), with the PUT method, would enable this property. Isn't this a concrete advantage of the "payment action".

dret

maybe the most interesting question is not so much that of the "Action URI" identifying the "Controller Resource", but whether the interactions are designed in a way so that there is no hidden context. if the payment representation submitted when following the payment link is self-describing (i.e., the payment identifies the order it is for by linking to it), then in fact it doesn't matter whether the payment URI is a subordinate of the order URI, the order URI itself, or a completely different URI. this also means that the whole interaction pattern works independent of the specific URIs being used, and that in fact might be the most important thing to look out for: there should be no "context creep" from URI structure to the way how interactions are being interpreted. is that a conclusion that others might be willing to subscribe to as well?

dret

felix, payment is not something that for business transactions should be considered idempotent. for sellers "idempotent payment" may be desirable (they happily accept repeated payments), but for buyers, they really only want to pay once, and if they pay more than once, that still buys them the thing, but not in way that is very advantageous for them.

Pedro Félix

1) I disagree: a payment system should ensure that a customer is only credit *once* for the *same* order, even if the seller receives multiple payment "messages" (e.g. customer retries in the event of failure). Using PUT would allow an HTTP intermediary to have this retry behavior automatically. Also, this idempotency characteristic would not have to be communicated out-of-band. It would be implicit by the use of the PUT method.

2) I agree that the payment representation should be self-describing and there should be "no context creep from URI structure". Namely, I agree with Amundsen that "self-describing affordances [should be] in the response". IMHO, this isn't incompatible with the use of PUT and "http://example.com/order/:id/payment".

Duncan-cragg

> you say "you know when you can pay because of the
> state of the Ticket, no link-rel necessary (it would
> always point to the Ticket anyway!)", but i don't
> quite get that. how do you represent the state and
> detect the fact that it's ready to accept payment?

Well, following the logic of this in steps: take out the redundant href, giving you [link rel="payment" /], which appears when it's possible to pay. Converting to a JSON representation, that could be { .. "payment": true .. }, or { .. "status": "payable" .. }. Just something about the state that indicates payability - in fact, it needn't even be overtly explicit like this.

> isn't one of the fundamental principles of REST that
> such a state change should be driven by hypermedia
> controls, and thus a state change would be exposed
> as a link a client can follow? that was my assumption,
> but it seems that you have something else in mind.
> how do you represent the state change in the resource?

Well that's the crux of the difference in thinking between my view of REST when applied outside of the normal document/browser Web, and that of the "link-rel-action" advocates! I go into excruciating detail on this subject in my description of FOREST, but I'll try to distill it a bit for this discussion... :-)

First, we've got to disentangle the two state systems: the resource or server state and the application or client state. Because POST isn't affected by the Hypermedia Constraint.

The Hypermedia Constraint describes the way that the state of a client is supposed to be constrained and guided by hyperlinks in the state of the server. This constraint thus applies to the GET side of REST. Indeed, links that you can jump, and GET, and cacheing, are the bulk of the subject matter of REST.

If it's a GET, the /client state/ changes. If it's a POST, the /server state/ changes!

You can usually then see the effects of your POST in the stuff you then GET: for example, if you were redirected to a resource after the POST. So that makes it look like the POST drove the client application state, but it didn't. That's still GET-side stuff.

So with this model, it doesn't make sense to manifest POSTability with a link that you POST to. Links are only for GET, for describing the hypermedia/hyperdata graph, for moving on /client/ application state.

To move /server/ resource state on, you POST to the resource - the GET-able resource! - that you're interacting with, that the documentation says would be interested.

Like you said, this means moving the 'verb' - or the 'intent' or the 'declaration of interesting client application state that may affect the server resource state' - into the POSTed content. You document that, when you see a server resource in 'this' state, it means you're good to POST your 'interesting client state' or 'action' (ugh) to it - and watch it change accordingly. This is a fundamentally declarative model, into which actions and verbs and imperative interactions have to be contrived.

REST is fundamentally declarative, is my claim.

That's my own re-interpretation of REST for machine-to-machine scenarios. Scenarios for which REST was not originally created, of course..

dret

hey duncan, thanks for the explanations. i am not quite sure i am buying it, though. if i have and require payments to be self-describing (i.e., link to the thing they are a payment for), then i can simply change that to and things will simply still work. meaning that if server state changes become more complicated than just affecting one resource, i can still handle that without having to change my order resource model. you would need to change the order model (and that would, btw, be a breaking change) if you had to make this change.

in our scenarios, many (in fact most) operations affect more than just resource, and thus we often have these "external links", often to processes. if you want to trigger some operation on a resource, you have to kick off a complete process, which in itself is a resource and, if it successfully completes, will eventually change the state of the resource that originally linked to the process. assuming that all resources are "self-contained" in the way that all interactions are just "running on that resource" would be way to restrictive. so while we might want to use the pattern for very simple interactions (such as updates), most interactions with resources will be more complicated than that and we need the ability to decouple the resource from the process that may use the resource and/or change the state of the resource.

Duncan-cragg

Well I think we're in violent agreement about a lot of this..!

I think we both agree that the payment POST body should be self-descriptive rather than depending on round-tripping information in an opaque, server-only payment link. In other words, the body representation needs two important elements: (1) an indication that this is a Payment, and (2) a link to the Order to which it applies.

This eliminates the significance of the "/order/42" and "payment" information encoded by the server inside your "http://example.com/order/42/payment" example, allowing us the freedom to POST the same body to resources other than per-resource, non-GET-able ones: such as the order itself, or a resource for processing payments.

It also allows us to inspect and understand the message body, without needing to dig into the server's link, etc. You may consider whether this means the Payment is also declarative and - horror! it's a POST! - idempotent ... ! :-)

Duncan-cragg

Next, I think you're saying "what if you want to add the ability to pay for several orders at once?" Your resource and interaction model has a layer of indirection via a link-rel to which we must POST the payment. This can be set to the order itself, but can be set later on to a "payment processor resource", to add multiple order payment functionality, without breaking single-order paying clients. (I don't know if you can GET your payment processor resource?)

On the other hand, my Payment POST was defined/documented as being sent directly to the Order (Ticket). Clearly, a link-rel to a (GET-able!) resource that handles payments could be built in to my resource interaction model instead. This link could even be added only when payment was possible.

But that would be nothing to do with satisfying REST and the Hypermedia Constraint; just a feature specific to this domain, to this resource and interaction model. And you don't need a link just for every POST you may want to do! That would be building in too much indirection "just in case".

Instead, look at your domain or resource model for GET-able links to real domain resources. My Orders (Tickets) have links to their "Dealer" object - which creates Tickets and holds lists of them. I could simply say I now allow multiple payments to be sent to that Dealer.

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Flickr