users@jersey.java.net

RE: [Jersey] JAX-RS == REST? Or not? (was Re: [Jersey] What HATEOAS actually means)

From: Markus Karg <markus.karg_at_gmx.net>
Date: Thu, 18 Feb 2010 20:43:40 +0100

Please see inlined. :-)

 

From: Kevin Duffey [mailto:andjarnic_at_yahoo.com]
Sent: Donnerstag, 18. Februar 2010 12:03
To: users_at_jersey.dev.java.net
Subject: RE: [Jersey] JAX-RS == REST? Or not? (was Re: [Jersey] What HATEOAS
actually means)

 


Hi Markus,

 

Thanks.. I understand what you mean more so now. I am still not quite sure I
see how asking a client to store their "cart" data rather than updating a
cart DB on the server side is any less restful. I say that because.. if we
can put an item in the cart and remove it from the available items that are
stored on the server side... why can't we keep the cart on the server side
as well? I understand the notion of statelessness.. but my understanding of
that is sort of how servlets and session cookies work.. stateful being the
session retains a cookie going back and forth... but moving that HttpSession
data to a DB table, while maintaining it's state.. the request/response are
stateless. From one request to the next, there is no state.. the logic in
the server side has to use something that comes in from the request to
figure out the stored state.. in my example, tying the authentication to a
user table, then from there being able to get the cart data/state from the
cart table based on that user. I guess I am unclear as to why this is
unRESTful.

 

If you put the httpsession in a db table, the request/response is *not*
stateless but explicitly *stateFUL*, as to answer the request of a client
you must lookup (remember) the state of the client! If you like to add new
items in the cart, you must remember what is already in that cart. So you
cannot just reduce the stock size and send the client back an updated cart,
but first you have to go to your hard drive and search for that cart. That
IS by definition stateFUL. And as per of the definition of REST in
Fielding's dissertation, that is not what people would expect a RESTful
system work like, as stateLESS is a need here.

 

Don't get confused by the fact that the server stores stuff in the database.
That is *not* the "state". It is just application data. The "state" is the
current status of the shopping process of one particular customer (what he
has in his cart, whether he wants to buy more, go to the cash desk, or just
leave the shop).

 

In a stateless scenario, a server does not need to remember the current
shopping status of any *client* but just about the status of the stock
(which is a singleton, while actually there are lots of customers -- see the
difference?). It can concentrate on the status of the items in stock. This
is much less work. See it like a supermarket: It is rather easy to have an
overview of all the shelves. But it is rather complex to keep track of who
has currently what in his cart, what happened to the cart, etc.

 

If you are storing the cart's content on the server side, then you have
several problems (for simplicity as examples of possible problems
resulting):

 

* Your system will be less scalable. Example: Think of all the shoppers that
grab a cart, start putting stuff into it and then leave the shop because
they changed their mind and don't want to actually buy the stuff. If the
cart is on the client, you can have virtually thousand of such
"non-shoppers" without any bit of place squandered on the server. You don't
have to do anything if one stops shopping. The cart just vanishes as the
client never will penetrate the server anymore. But if you have the
state-of-shopping for each client on the server, then you have to actively
remove it from your RAM and / or harddisk. At about 500 shoppers you might
run out of place, possibly. With client side carts (unless they actively do
something) there is virtually ZERO RAM / harddisk place needed for an
virtually unlimited number of (passive) clients.

 

* Complexity: It is much simpler to write a stateless server, as it must not
remember anything but it's own stock (but nothing about a particular
client's status).

 

 

Also, what drives me to drill down on this is some stuff I am working on
when I can spare some cycles... an eventual public service that might be
consumed by many developers. I don't know how I explain to them that my API
is a true RESTful API and as such, they must send me (and thus maintain) the
state on every request (depending on the URI chosen by the client... if they
choose Cancel, of course they don't have to send all the contents). I
suppose this is where I thought REST would be so beautiful.. using such an
easy HTTP call with minimal effort to add new items to the cart, get a list
of what is in the cart, delete an item from the cart. Having every developer
actually maintain and send me the cart contents every time a link is pressed
(that requires the "state" of the cart.. it's contents), seem's deterring to
me. I can imagine a lot of developer not understanding why this is done this
way. In other words, it almost seems like for me to provide a really
nice/easy RESTful API, I also have to provide some URIs that are NOT REST
based calls in order to maintain the state of a cart on the server side. I
am having a hard time grappling with this mixed API design.... on the one
hand, the server side keeps a DB of items that can be manipulated.. added to
the cart, updated, etc. On the other hand, the actual cart data for each
user is up to them (er..the developer consuming the API) to keep track of
send when needed, etc.

 

If you want to spare cycles, you should first think over what part of
cycles. If you want to spare CPU / HDD cycles, then you're better of if you
put the cart on the client, since it is the client's sole problem then and
the server is freed from it. If you want to spare client/server roundtrips,
then you should explane why you like to do so. As each "put this item in the
cart" action is just one roundtrip, I do not see how you could reduce that
by storing the cart on the server?

 

I do not understand what problem you have with explaining customers that
they must store state. This is typical in REST, so just tell them how it is.
Turn the idea around and look it that way: Why do you like to keep the cart
on the server? What benefit would this bring? If a developer doesn't
understand it then tell him the above examples with the lots of RAM you
would need to reserver on the server just for the cart of each possibly
orphaned client.

 

I do not see that you need a mixed API. Just drop the idea of keeping the
cart on the server. There is no real benefit from a cart on the server.

 

Again, remember the real worl shop: Are you (client) walking through the
shop with your own list in hand of what to buy, picking items and putting
them in your cart (so *you* have full control of what happens with the cart
and with the items on your list), or do you give the list to the manager,
waiting for all the stuff coming back, just saying "next one, next one"
after each provided item?

 

 

So let me throw this out there.. I'll probably get slammed for it..
especially if Roy reads it.. but perhaps while Roy's REST is sort of gospel
right now, perhaps this sort of hybrid use of REST is more useful than just
pure REST.. and I know you and others are not saying we CANT do this.. but
if the REST community is pushing the notion of REST.. and more and more
developers (like myself) start to understand what a truly RESTful API is and
doing it right, then some of the things I thought the REST I was doing
(which are probably more HTTP RPC) go away.. and now I can't offer a pure
REST API to do things like provide a public CART service that does NOT
entail the client side having to maintain the cart contents. I like the
"current" REST ways because it allows a much easier to use API than web
services. Using the simplicity of HTTP calls with authentication as many of
us do now, even those of us not using HATEOAS but publishing a SDK doc that
indicates ALL the urls a consumer can make at any point (as long as
authentication works).. I don't know.. it just seems to alleviate a lot of
the web services, SOAP, stuff like that that while not terribly difficult,
is not nearly as clean/pretty as this sort of ad-hoc REST a lot of us are
currently employing. So maybe rather than pushing this idea of pure REST on
the community, we should coin what I think you and/or Jan call an HTTP
API... perhaps come up with a better name for it.. or maybe not... I
honestly don't know if I would want to become a pure REST based API with
what I feel are now limitations of the meaning of a RESTful API. I like that
I can provide an SDK doc with clear info on calls, what to send in, and what
comes back under various circumstances. I like the idea of HATEOAS even
better, but with the same context of how I am using REST with Jersey today..
publish a SDK doc that indicates the first URL to go to, depending on
authentication you'll get back some subset of links you can then use. From
there, it goes on and on, but at least things like state that the service
provides can be contained in a dB on the server side and still provide a
very clean easy to use REST-like API and keep the client side relatively
easy as well.

 

Actually mixed APIs are not more useful, they just make it harder to
understand what part is working in what way.

 

I would really please you to provide an example why the cart *must* stay on
the server. What actual problem will it solve? What actual benefit will it
bring? If you really think that "some" http API is better than a "real" REST
API, why do you want it being part of JAX-RS (i. e. Java API for RESTful
WebServices) instead of e. g. Servlet API?



--- On Wed, 2/17/10, Markus Karg <markus.karg_at_gmx.net> wrote:


From: Markus Karg <markus.karg_at_gmx.net>
Subject: RE: [Jersey] JAX-RS == REST? Or not? (was Re: [Jersey] What HATEOAS
actually means)
To: users_at_jersey.dev.java.net
Date: Wednesday, February 17, 2010, 9:53 AM

There is a misunderstanding.

 

As Marc already explained, what is meant with "stateless" is "state of
workflow", not "state of resource". Example:

 

Your business process is that you want to fill your cart, and then go to the
cash desk. To "run" this by the client, the client must know whether you
already have paid or not (unless you would pay twice). This information is
not interesting for the server, as the supermarket is not interested in what
you bought after you paid and left the shop. But it is of interest, what
went out of stock or what the monthly income was.

 

So the server stores how many items are there of each article, and it also
stores the sum you paid. That information is "state of resource", but this
is not what our "stateless" discussion is about.

 

The discussion is about the fact that in the above workflow, the server
*must not* store the information what you have in your shopping cart, or
whether you have paid already. This information is stored solely by the
client. If the client puts more stuff in the cart, it will send the server
the current cart's content, the server "enriches" it be the new item AND BY
A "PAY BY VISA" LINK, and sends the more-filled cart content description XML
/ JSON back. Then it forgets about what it has done so far (despite the fact
that it reduces stock, see above). When you want to pay, you again upload
the cart's content to the server ("you put everything on the cash desk"),
VISA gets charged (thanks to the "PAY BY VISA" link that the server added to
the returned content!), and the server returns a document IN WHICH THE VISA
LINK *IS MISSING*, but in which a "Leave the shop" link is found. Then the
server forgets about this (but stores the sum you paid for later reporting).
Since the server removed the VISA link, the client has no more knowledge how
to pay, so you prevent that one goes to the cash desk twice. Thanks to the
"Leave the shop" link, the client can terminate the workflow.

 

As you can see, it is solely the client that drives the process and knows
about the previous and next steps. How? Since it stores the current
"workflow state" (here: the cart's content AND THE VALID LINKS) on behalf of
the client. Even if you shutdown the server meanwhile, you can reboot it, it
will not need to know anything about the workflow so far: The client know
it! The client inspects the links found in the latest response, and checks:
Can I order more (is there a link with the role "add more stuff in the
cart"?)? Can I pay (is there a VISA link?)? Can I leave the shop (is there a
"leave" link)? Exactly THAT is HATEOAS. :-)

 

About your authentication question: The above scenario will forget
authentication and re-authenticate with each call. So nothing will happen if
the server is shut down or load-balanced or fail-over'ed. Typical
non-RESTful scenarios (RPC) will have long-term authentication. If the
server is shut down, authentication is gone, and the workflow will most
typically rollback.

 

The other part of the discussion was about generic vs. specialized clients.
Jan wants to do spezialized clients, i. e. a client that know where to find
such links (besides in the entity aka document itself) and possibly the role
names of the links, while my idea is to have a generic client that can be
scripted from outside, so the script provides the information what role's
link is of next interest (like "genericClient.invoke("roleName");").

 

HTH

Markus

 

From: Kevin Duffey [mailto:andjarnic_at_yahoo.com]
Sent: Dienstag, 16. Februar 2010 21:44
To: users_at_jersey.dev.java.net
Subject: Re: [Jersey] JAX-RS == REST? Or not? (was Re: [Jersey] What HATEOAS
actually means)

 


Excellent!! +1 here too. I've bookmarked the links, I'll check back next
week to see any progress you make Felipe. I am really interested in seeing
how you (and others) are going about handling the HATEOAS responses.


I am also interested in understanding more from some of the other threads
about how the server does NOT maintain any state... per se... I guess I am
defining state differently perhaps, but to me, if you create/update
something using a URI, their is usually some database storing that data. If
I add a user via a POST, the XML/JSON I send is being stored in a DB. To me,
that is stateful. With the same authentication on subsequent calls, I could
maintain a sort of state. Same thing with a shopping cart. If I have a cart
DB table, and a user POSTs to a URI that adds an item to the cart, the logic
on the back end stores that item in the cart DB table associated with the
request (and the user making that request). Sure, the request/response
itself is stateless.. but the Authentication header allows me to verify (on
every call) a user and from that I can associate "state" using that user's
authenticated info and some other table(s) for the request specific
resourses. Am I missing some understanding about this process? Is it
correct.. or is there some better more RESTful way to do this?

So definitely want to follow the wiki and see how ya'll are workign thru
HATEOAS responses and maintaining a "quasi" state I suppose.

Thanks.


--- On Tue, 2/16/10, Felipe Gaścho <fgaucho_at_gmail.com> wrote:


From: Felipe Gaścho <fgaucho_at_gmail.com>
Subject: Re: [Jersey] JAX-RS == REST? Or not? (was Re: [Jersey] What HATEOAS
actually means)
To: users_at_jersey.dev.java.net
Date: Tuesday, February 16, 2010, 3:46 AM

ok, I created two Jersey children pages:

"Samples" - that should be our catalog of examples
 <http://wikis.sun.com/display/Jersey/Samples>
http://wikis.sun.com/display/Jersey/Samples

"Samples/PUJ" - my business scenario page..
 <http://wikis.sun.com/display/Jersey/PUJ>
http://wikis.sun.com/display/Jersey/PUJ

I will try to be as fast as possible (probably in the weekend I find time).
As soon I have the first draft out there I ask your review - I plan to use
this page as sketchboard of my HATEOAS experiments. You all are invited to
contribute.

Thanks for the opportunity, and feel free to move the pages on the Jersey
wiki if you prefer other names or locations.




On Tue, Feb 16, 2010 at 12:27 PM, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:

Hi Felipe,

 

A most excellent idea. Thank you for offering to do this, your contribution
is most welcome.

 

You can use the Jersey wiki. Anyone with an account can edit and add pages.

 

   <http://wikis.sun.com/display/Jersey/Main>
http://wikis.sun.com/display/Jersey/Main

 

 

Santiago already put together a page for his ideas:

 

   <http://wikis.sun.com/display/Jersey/Hypermedia+and+Client+APIs>
http://wikis.sun.com/display/Jersey/Hypermedia+and+Client+APIs

 

I am not sure if that page is suitable to link from for what you are
suggesting. I suspect we need a more general hypermedia page to link from
with a set of one or more cases from which solutions can be derived.

 

 

Also since you have implemented your business case i think you have a good
understand of what support Jersey can better provide to make it easier for
you.

 

Paul.

 

On Feb 16, 2010, at 9:56 AM, Felipe Gaścho wrote:

 

Hi there,

I would like to donate my business scenario as test bed for HATEOAS
implemented with JAX-RS.

What I need: a wiki page somewhere where I can describe my business case.
Then I start and other people can review and rewrite the parts they believe
wrong. We can have in short period of time a benchmark case. I will write
down only the business scenario and the suggested resources representation.

After that, everyone can implement that case in the way they believe better,
in which technology they believe better :)

Why to use my case instead of others?

1) Because the implementation of such project helps education in Brazil (
<http://kenai.com/projects/puj/pages/Home>
http://kenai.com/projects/puj/pages/Home)
2) Because it is generic enough to be adopted by other JUGs
3) Because it is open-source and there are already some implementation
available

* Of course, we can also think about a "catalog" where several people
contribute with business scenarios, and eventually the more complete one
will emerge from this brain storm.

If you like the idea, please point me the wiki I can start to write down the
spec of PUJ.

* I will try this anyway, bu if I have the community attention I will get
some extra push :)

thanks,

   Felipe Gaścho



On Tue, Feb 16, 2010 at 9:50 AM, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:

Hi Kevin,

 

The Sun Cloud API is RESTful. Trust me :-)

 

We need to address your point about examples, with use-cases, when we have
more solid API details around hypertext and JAX-RS.

 

People are already developing hypertext applications using JAX-RS they are
just doing the work themselves. For example, Felipe is doing just that (he a
link on this list to some slides out recently). IIRC Marc, and he can
confirm or deny, has developed hypertext applications in the identity space
using JAX-RS, but i do not think those are public. And i am sure others have
developed similar examples.

 

Paul.

 

On Feb 16, 2010, at 8:29 AM, Kevin Duffey wrote:

 



> Hopefully we can clarify this further with more concrete examples.

 

I hope soon.. I would really like to know the "right way" to build HATEOAS
apis. :D

 

I have read this extremely long thread, and am really really confused now as
to what is what. I thought the Sun cloud APIs was a completely restful API
design. However, this notion that the client maintains state has got me a
bit confused now. I would love to see some truly RESTful examples using
Jersey/JAX-RS.. how to implement for example HATEOAS in the present JAX-RS
such that I can claim my API is truly RESTful and that everyone on this
thread would agree on.

 

 

 

 

 




-- 
------------------------------------------
  Felipe Gaścho
  10+ Java Programmer
  CEJUG Senior Advisor
 
-- 
------------------------------------------
  Felipe Gaścho
  10+ Java Programmer
  CEJUG Senior Advisor