RE: the meaning of stateless
"Markus Lanthaler" <[email protected]>
| Newsgroups | gmane.comp.web.services.rest |
|---|---|
| Message-ID | <[email protected]> |
Hi Mike,
I'm trying to consolidate all your questions in the various sub-threads
answer them in a single mail.
> If that is absolutely true, then how can REST implement workflow or
> transactions? For example (admittedly trivial, but the pattern could
> be applied to something much less than trivial):
>
> GET /client/abc123/accounts
> ---> 200 ok, [ { "account": "checking", "balance": 500.00 },
> { "account": "savings", "balance": 100.00 }]
> POST /client/abc123/account-transfer/new
> ---> 200 ok, Location: /account-transfer/12345
> PUT /client/abc123/account-transfer/12345/checking
> balance=350
> ---> 200 ok
>
> PUT /client/abc123/account-transfer/12345/savings
> balance=250
> ---> 200 ok
>
> POST /client/abc123/account-transfer/12345
> action=commit
> ---> 200 ok
>
> In the real world I can come up with all kind of other examples where
> an action based on a POST would be different based on POSTs and PUTs
> that came before it, or the thing that needs to be accomplished cannot
> be. So my intuition tells me that there must be some kind of state
> that is okay and some kind of state that is bad but the more questions
> I ask the less I'm confident that I understand the answer. Based on
> your comment I would be driven to think that systems cannot implement
> workflow or transactions and still be RESTful.
That's true and I think that's where your confusion comes from. There are
indeed two types of states: application state and resource state.
The statelessness of REST is about the application state. The client is
responsible for the application state. For example, if you browse through a
paginated collection the server must not keep track of the last page the
client visited. That's up to client. Obviously the server could store that
information in a session record but that would lead to reduced scalability.
On the other hand there's resource state. That's the state the server is
responsible for. Every HTML page you are able to retrieve on the Web
represents such resource state. The difference is that that state is not
bound to a single client but available to all clients (given they are
authorized).
The example above is stateless in that respect. Any client knowing the
account transfer ID can go and modify it. I would change the last POST to a
PUT because otherwise you wouldn't be able to repeat the commit if the POST
fails. If the server receives another commit for an already committed
transfer it can simply ignore it. Obviously cancelling a committed transfer
would have to result in an error.
> On Apr 24, 2013, at 1:23 PM, Markus Lanthaler wrote:
> > No, it's not their "implicitness" it is because the server has to keep
> > track of the clients. The server typically creates a small file (or DB
> > entry) in which he puts session information about the client. You need
> > to replicate that to all servers if you want to scale such a system.
>
> So earlier in the thread I asked[1] if a shopping cart or transaction
> that creates a DB entry violates the stateless requirement and the
> only person who answered said it did not[2].
That's true. It does not because it is resource state. In a Web API a
shopping cart IMO however doesn't make much sense. Just create directly an
order.
> Is he wrong and if so then are RESTful systems not able to do workflow
> or transactions? Or is he correct and there is some other nuance that
> differentiates between a session and a shopping cart or a transaction?
Hope the explanation above answered this question.
> > Yes.. you should also add that a request *must not* depend on a
> > previous request (the use of a session ID, e.g., does)
>
> I just asked Mark Baker today about this giving an example transaction
> that does depend on a previous request[3] which was similar to what
> was recommended in Richardson & Ruby's REST book. So I'll repeat the
> above question: are RESTful systems not able to do workflow or
> transactions? Or is there some other nuance that differentiates
> between a session and a shopping cart or a transaction?
See above.
> I'm not trolling, I'm honestly trying to come up with a way to
> understand Roy's Rules of REST in a concrete, objective and
> unambiguous manner so I can be sure that I'm always employing them
> correctly and I don't feel I can do that yet.
No need to apologize :-)
> On Apr 24, 2013, at 9:34 PM, Mark Baker <[email protected]> wrote:
> > Remember the days before electronic banking when we had to fill out
> > slips and submit them to a teller?
> >
> > POST /transfer-request
> > {"from": "http://example.org/acct/12345",
> > "to": "http://example.org/acct/12346",
> > "amount": 300 }
This is a particularly bad example IMHO. What would do if the POST fails?
For example if you lose your WiFi connection before you get a response?
Obviously you can't just repeat it. Mike's approach is much better in that
regard.
> Anyway, let me take your example which I assume is RESTful and ask my
> question another way. It seems to me that if I started with a state of
> "500" in account "12345" and "0" in account "12346" and do your POST
> example I end up with "200" and "300" in the accounts, respectively.
>
> However if I now do your POST example *again* it will fail, because I
> don't have enough money in the "from" account to complete the
> transaction. So how are the account balances not "state" in the
> context of Roy's "stateless" requirement?
They are state - resource state however.
> If you tell me the reality is that most non-trivial uses-cases for a
> web APIs actually need to be stateful in some ways and that the
> "stateless" requirement for REST is an ideal that has benefits when it
> can be achieved but is often impossible to realize then I think I'd be
> finally coming to an understanding of the stateless requirement. :-)
>
> But if you say "No, stateless can be achieved in most cases" then I'm
> even more lost than when I started asking questions on this thread a
> few days ago. :-(
All that counts is that the server doesn't need to keep track of client
state (= application state). As long as you do that, you can throw more
stateless boxes in front of your database (managing the resource state) to
scale your service. If the servers would need to manage client sessions
(again, application state) you can't do that so easily because.
Cheers,
Markus
--
Markus Lanthaler
@markuslanthaler