users@jersey.java.net

[Jersey] Re: stateless REST

From: Robert Gacki <robert.gacki_at_contenttrace.org>
Date: Fri, 10 Jun 2016 23:45:47 +0200

Again: If you use cookies, you are "REST-compliant". It's just a
header.

Yes, in your example, sending the data of page 1 also in page 2 is a
good and simple solution, and is sufficient if you don't want the
client to be able to continue on page 2, after the client lost its
state. Its how we built wizards "in the dark ages of the web".

If you need the client to resume from page 2, you can also do something
like the following requests / responses:

-- req/1 -----------------------------------
GET /wizard HTTP/1.1
Accept: text/html

-- res/1
HTTP/1.1 200 OK
Content-Type: text/html

<form action="/wizard" method="post"></form>


-- req/2 -----------------------------------
POST /wizard/1234/step1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Accept: text/html

formdata

-- res/1
HTTP/1.1 201 Created
Content-Type: text/html
Location: /wizard/1234/step1

<form action="/wizard/1234/step2" method="post"></form>
<a rel="self" href="/wizard/1234/step1">Link to this step</a>

-- req/3 -----------------------------------
POST /wizard/1234/step2
HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Accept:
text/html

formdata

-- res/1
HTTP/1.1 200 OK
Content-Type: text/html

<p>Thank you for doing whatever it was!</p>

-- req/4 -----------------------------------
GET /wizard/1234/step1 HTTP/1.1
Accept: text/html

-- res/4
HTTP/1.1 410 Gone
Content-Type: text/html

<p>The wizard step does not exist anymore, because the thing was finished.</p>

snip ----------

Of course, the entire thing needs to be implemented and is more complex than just the simple resend solution.

Robert


Am Freitag, den 10.06.2016, 15:11 -0600 schrieb Trenton D. Adams:
> That's just semantics though.  For any statefulness to occur, a
> common token would be required.  Whether that token is implicit such
> as an IP, or crafted, such as a JSESSIONID, it's still a token none
> the less.  So I'm thinking the use of cookies, to send session
> tokens, isn't in keeping with REST principles.
>
> Let's take an example where someone is admitting to a university.
>
> 1. Page 1 contains biographical information, which the student
> submits.
> 2. Page 2 contains program/major information.
>
> In keeping with REST principles, you'd have to submit data from page
> 1, and page 2, on page 2.  Alternatively you could commit information
> from page 1 to a database, and simply pass a student ID on page 2
> with the extra info on your program.  Both would be in keeping with
> REST principles.  Storing page 1 info on the server side, and passing
> just a cookie to identify the session on page 2, is NOT in keeping
> with rest principles.  Why?  Because it's not scalable.  You'd have
> to specifically take action to make sure session state is copied
> between servers.  There are technologies for that, but REST is
> intended to avoid the need.  Hence transferring the entire state from
> the client to the server on every request, not just a token for a
> session.
>
> Personally, I care very little about scalability.  We're not
> facebook, twitter, etc.  We would at most scale to 2-3 servers, just
> for redundancy reasons, not load reasons.  If I were to scale to 1000
> servers, I'd want to start thinking about sticking very strictly with
> REST principles.
>
> On Fri, Jun 10, 2016 at 2:44 PM, Robert Gacki <robert.gacki_at_contenttr
> ace.org> wrote:
> > Cookies in the scope of HTTP and REST are stateless. It is the
> > "Cookie"
> > header.
> >
> > The client and the server have to agree that data, that is sent via
> > Cookie header, comprises a session that is relevant in subsequent
> > requests (we call it then a "session").
> >
> > So Cookie is just a header and thus 100% stateless.
> >
> > Although, the cookie may be stored on the client and may be send by
> > subsequent requests (following the RFC constraints about domains
> > and
> > paths and expiry and all that stuff). And even this is compliant
> > with
> > the REST principle.
> >
> > So if you use cookies, you are align with the REST principles.
> >
> > Robert
> >
> > Am Freitag, den 10.06.2016, 15:27 -0500 schrieb Tony Zakula:
> > > I would use what works and what is best for you.  Standards are
> > > great, but we do not have to be purists in everything we do to
> > get
> > > work done.  Jersey still runs on a servlet and you can easily tap
> > > that session if you want to, nothing wrong with that.  HTTP that
> > REST
> > > is built on even supports cookies for the session.  What is wrong
> > > with mixing and matching a few pieces to make building your app
> > > easy?  Nothing.  You can even support stateless and state on the
> > same
> > > API calls with Jersey to satisfy different clients.  Mobile apps
> > may
> > > store state and web browsers do not.  Offer both if needed.  Your
> > app
> > > will still work even if you do not adhere to the standard.
> > >
> > > In the end, build an app to fit your use case and that works well
> > for
> > > you.   
> > >
> > >
> > > On Fri, Jun 10, 2016 at 2:38 PM, Trenton D. Adams <trenton.d.adam
> > s_at_gm
> > > ail.com> wrote:
> > > > Your descriptions of what REST is what I would like it to be,
> > but
> > > > it isn't that, accrording to most everything I've read on it. 
> > If
> > > > you're storing state, you're not using REST.  The use of REST
> > > > precludes maintaing state server side.  I'm tempted to use JAX-
> > RS
> > > > regardless, and just not use the statelessness part.
> > > >
> > > > https://en.wikipedia.org/wiki/Representational_state_transfer#S
> > tate
> > > > less
> > > > Stateless
> > > > See also: Stateless protocol
> > > > The client–server communication is further constrained by no
> > client
> > > > context being stored on the server between requests. Each
> > request
> > > > from any client contains all the information necessary to
> > service
> > > > the request, and session state is held in the client. The
> > session
> > > > state can be transferred by the server to another service such
> > as a
> > > > database to maintain a persistent state for a period and allow
> > > > authentication. The client begins sending requests when it is
> > ready
> > > > to make the transition to a new state. While one or more
> > requests
> > > > are outstanding, the client is considered to be in transition.
> > The
> > > > representation of each application state contains links that
> > may be
> > > > used the next time the client chooses to initiate a new state-
> > > > transition.[12]
> > > >
> > > >
> > > > On Fri, Jun 10, 2016 at 1:04 PM, Robert Gacki <robert.gacki_at_con
> > tent
> > > > trace.org> wrote:
> > > > > Hi Trenton,
> > > > >
> > > > > I think, you misunderstand what REST is. REST is about how a
> > > > > server and
> > > > > a client interacts to transfer state. The transport itself is
> > > > > stateless
> > > > > ("dumb pipes"). It is an architectural style. The notion of
> > state
> > > > > is
> > > > > something the client and server have to implement themself.
> > What
> > > > > REST
> > > > > describes is nothing else what HTTP specifies, but is not
> > limited
> > > > > to
> > > > > HTTP (think of mail). In fact, Roy Fielding just took HTTP as
> > an
> > > > > example for REST in his dissertation.
> > > > >
> > > > > OSI Layer
> > > > > ----------------------------------------------------
> > > > > | Your server and/or client application      | L   |
> > > > > ---------------------------------------------- a   |
> > > > > | REST as architectural style                | y 7 |
> > > > > ---------------------------------------------- e   |
> > > > > | HTTP|MAIL|<other req / res based protocols>| r   |
> > > > > ----------------------------------------------------
> > > > >   Layer 6 and below
> > > > >
> > > > > JAX RS is only about modelling REST principles and Jersey
> > > > > provides the
> > > > > implementation. That does not include state management. So
> > you
> > > > > should
> > > > > see JAX RS as the protocol toolset ("dumb pipes") to build
> > > > > applications. What you call stateful is application state and
> > > > > that is
> > > > > always application / implementation specific. For example,
> > the
> > > > > notion
> > > > > of a session is purely application specific.
> > > > >
> > > > > So Jersey, at its core, does not provide you with components
> > to
> > > > > build
> > > > > things like a wizard. But it provides you the ability to
> > build or
> > > > > use
> > > > > existing components, like JSR 371 and its implementations.
> > > > >
> > > > > To your wizard example: You can solve wizards with different
> > > > > methods.
> > > > > You described one solution, where the server does not store
> > > > > results of
> > > > > previous wizard steps. Each solution has advantages and
> > > > > disadvantages.
> > > > > But all solutions have something in common: they are
> > application
> > > > > specific. If you use HTTP as a communication protocol, you
> > can
> > > > > use REST
> > > > > principles to have a well-defined architectural style. But
> > you
> > > > > still
> > > > > need to figure out how to maintain state between a request
> > and
> > > > > response.
> > > > >
> > > > > An important part of REST is Hypermedia. For HTTP, this is
> > just
> > > > > payload. For an application built by REST principles, it is
> > the
> > > > > state
> > > > > that is transfered. And that state should include all
> > information
> > > > > necessary for server or client to support continous
> > interactions.
> > > > > If
> > > > > you use your browser and surf around, clicking on links or
> > > > > signing in
> > > > > into your Google account, you are doing exactly what REST
> > > > > proposes for
> > > > > all other media types - not just HTML.
> > > > >
> > > > > So your wizard solution is based on HTML (a representation)
> > and
> > > > > is
> > > > > constraint by the HTML specification and how browsers behave.
> > > > > Thus, you
> > > > > may lose form field values when you use the browser's back
> > > > > button. But
> > > > > you can do three things to counter that without storing state
> > > > > server-
> > > > > side (outside request-response bounds): 1) You can provide a
> > back
> > > > > button inside the form that just submits to the server - the
> > > > > server
> > > > > renders the previous page with the values from the hidden
> > fields.
> > > > > 2) In
> > > > > modern browsers, with Javascript enabled, you can store the
> > state
> > > > > client side and restore it when the user goes back. 3) SPAs
> > > > > mostly
> > > > > avoid the problem by avoiding round-trips to the server, with
> > the
> > > > > disadvantage of cloning lots of server-side logic for the
> > client
> > > > > (validation, business logic).
> > > > >
> > > > > Robert
> > > > >  
> > > > >
> > > > > Am Freitag, den 10.06.2016, 12:11 -0600 schrieb Trenton D.
> > Adams:
> > > > > > Thanks for the responses guys.  I'm thinking more along the
> > > > > lines of
> > > > > > JAX-RS implementations, such as Jersey, providing a
> > template
> > > > > based
> > > > > > approach, where the result can be served by JSP. 
> > Technically,
> > > > > that's
> > > > > > almost useless when doing it statelessly, unless your
> > service
> > > > > is
> > > > > > intended to return HTML to a client program, or you intend
> > to
> > > > > violate
> > > > > > the statelessness of REST.  Cause like you say, writing
> > BBAs,
> > > > > is
> > > > > > actually quite tough without some nice statefulness.
> > > > > >
> > > > > > JSR 371 will be coming out too.  Are they still expecting
> > > > > stateless? 
> > > > > > Cause it suddenly becomes less useful.  Maintaining all the
> > > > > state in
> > > > > > the browser's store is a lot of extra work, and just a
> > plain
> > > > > weird
> > > > > > way of dealing with it.
> > > > > >
> > > > > > On Fri, Jun 10, 2016 at 10:07 AM, <lenny_at_flowlogix.com>
> > wrote:
> > > > > > > Trenton, I feel your pain.
> > > > > > > In all honesty, the technology architecture didn’t change
> > all
> > > > > that
> > > > > > > much in the last 10 years.
> > > > > > > Don’t get caught up in the Rest/Microservices hype too
> > much.
> > > > > > > For BBAs (boring business apps) which I believe that you
> > are
> > > > > > > dealing with (and I also like developing),
> > > > > > > it makes very little sense migrating to Rest-based
> > > > > architecture.
> > > > > > > Concentrate on cleaning, refactoring, modularizing your
> > code,
> > > > > using
> > > > > > > the latest iterations of Java EE specs that you are
> > already
> > > > > using.
> > > > > > >
> > > > > > > So, why all the hype?
> > > > > > > Current Rest “state-of-the-art” today is actually in it’s
> > > > > very
> > > > > > > infancy. It makes sense for some applications to do it
> > > > > though, but
> > > > > > > not for BBAs.
> > > > > > > What apps does the Stateless Rest APIs make sense for?
> > > > > > > - Multiple clients written separately by different teams
> > > > > (i.e.
> > > > > > > native iOS, native Android, native JavaScript)
> > > > > > > - APIs that other companies use in different (non-Java)
> > > > > languages
> > > > > > > - There are some other use cases also, but the above are
> > the
> > > > > major
> > > > > > > ones
> > > > > > >
> > > > > > > What’s the negative impact of Rest services today, as it
> > > > > relates to
> > > > > > > Java client and server development?
> > > > > > > - Massive violation of DRY principle, as it’s really
> > meant
> > > > > for
> > > > > > > client and server to be written in different languages,
> > > > > > > i.e. client in JavaScript/iOS/Android and server in Java
> > > > > > > - Data models are duplicated both in Java (on the server)
> > and
> > > > > on
> > > > > > > the client (JS/iOS/Android)
> > > > > > > - Validation is duplicated on the client and server
> > > > > > > - Some business logic may need to be duplicated in the
> > client
> > > > > and
> > > > > > > server
> > > > > > >
> > > > > > > The above negatives are something that are not solved by
> > the
> > > > > > > industry quite yet, and for BBAs, (IMHO) is not worth the
> > > > > effort.
> > > > > > >
> > > > > > > As far as answering your specific question, in “pure”
> > Rest
> > > > > API, All
> > > > > > > state is indeed handled by the client, including
> > > > > authentication.
> > > > > > > Authentication is usually handled by “bearer token”
> > paradigm,
> > > > > is
> > > > > > > sent with every request to the server, and thus re-
> > > > > authenticated by
> > > > > > > the server every time.
> > > > > > > Yes, it sounds (and is) a bit less efficient on per-
> > request
> > > > > basis
> > > > > > > (throughput per instance), but does (horizontally) scale
> > > > > better to
> > > > > > > millions of users.
> > > > > > >
> > > > > > >
> > > > > > > > On Jun 9, 2016, at 4:40 PM, Trenton D. Adams
> > <trenton.d.ada
> > > > > ms_at_gma
> > > > > > > > il.com> wrote:
> > > > > > > >
> > > > > > > > One thing I didn't mention, is that I'm considering
> > > > > updating one
> > > > > > > > of our enterprise apps to more modern technologies,
> > where
> > > > > it
> > > > > > > > actually saves effort.  It is currently based on RMI,
> > with
> > > > > a
> > > > > > > > custom web front-end/mvc framework based on a the
> > command
> > > > > > > > pattern.  So, I'm trying to determine whether we should
> > do
> > > > > EJB or
> > > > > > > > JAX-RS for the back-end, and possibly JAX-RS for the
> > front
> > > > > end. 
> > > > > > > > One of the issues is that EJB is almost a drop in
> > > > > replacement for
> > > > > > > > RMI.  It would require significant more effort to
> > switch to
> > > > > JAX-
> > > > > > > > RS.
> > > > > > > >
> > > > > > > > When the back end is stateless, it's simply pushing the
> > > > > > > > complexity to the client.  It is now the client that
> > must
> > > > > do all
> > > > > > > > the work to know what it needs to send; i.e. it keeps
> > it's
> > > > > own
> > > > > > > > state.  For the back end, that's HIGHLY scale-able
> > > > > technology
> > > > > > > > wise, but has other drawbacks.  With a stateful back-
> > end,
> > > > > you
> > > > > > > > just set the firstname, lastname, birthdate, etc, and
> > pass
> > > > > around
> > > > > > > > a reference to the back-end object, such as with EJB. 
> > > > > Neither
> > > > > > > > the front end nor the back end have to maintain much
> > state,
> > > > > > > > programmatically speaking; it's the service that does
> > that
> > > > > (EJB
> > > > > > > > for example).  This saves developer time, does it not?
> > > > > > > >
> > > > > > > > It seems that using the html5 stuff would be a pain in
> > the
> > > > > butt. 
> > > > > > > > Mainly because html5's storage system can't store a
> > > > > javascript
> > > > > > > > object even, so you can't even abstract your data
> > storage. 
> > > > > Plus,
> > > > > > > > we'd end up not supporting people with older
> > > > > machines/browsers. 
> > > > > > > > And then, if you have a series of web pages that a
> > person
> > > > > is
> > > > > > > > going through, you'd have to write code to grab all of
> > > > > that, and
> > > > > > > > pass it to the server.
> > > > > > > >
> > > > > > > > So, should I not use JAX-RS if I'm wanting to maintain
> > > > > state?  I
> > > > > > > > mean it kind of goes against the "ST" in REST.  Nothing
> > > > > actually
> > > > > > > > prevents you from maintaining state though.
> > > > > > > >
> > > > > > > > I've read some articles where people say you shouldn't
> > even
> > > > > be
> > > > > > > > maintaining state of authentication.  That I don't
> > agree
> > > > > with,
> > > > > > > > because some services don't even have access to the
> > user's
> > > > > > > > credentials.  So at some point, someone is going to
> > have to
> > > > > > > > maintain state.  So, you could either not use JAX-RS,
> > or
> > > > > use it
> > > > > > > > and maintain state while doing so, but essentially
> > violate
> > > > > it's
> > > > > > > > principles.
> > > > > > > >
> > > > > > > > Also, doesn't statelessness become very complex when
> > you
> > > > > have
> > > > > > > > larger enterprise applications?
> > > > > > > >
> > > > > > > > I see a lot of benefits of JAX-RS, and a lot of
> > drawbacks. 
> > > > > Am I
> > > > > > > > missing something?
> > > > > > > >
> > > > > > > > On Wed, Jun 8, 2016 at 5:46 PM, cowwoc <cowwoc_at_bbs.dark
> > tech
> > > > > .org>
> > > > > > > > wrote:
> > > > > > > > > Define "application logic".
> > > > > > > > >
> > > > > > > > > In the case you mentioned below (storing the user's
> > last
> > > > > name
> > > > > > > > > somewhere) I would favor using localStorage and
> > > > > sessionStore to
> > > > > > > > > store this information: http://www.w3schools.com/html
> > /htm
> > > > > l5_web
> > > > > > > > > storage.asp
> > > > > > > > > The client would read the information from the local
> > > > > store and
> > > > > > > > > use it to make AJAX calls.
> > > > > > > > >
> > > > > > > > > I misspoke earlier when I talked about Cookies. These
> > are
> > > > > > > > > typically used to reference to a server-side state
> > that
> > > > > is
> > > > > > > > > present across all calls. If some REST calls need one
> > > > > piece of
> > > > > > > > > information and others need another, I would pull
> > them
> > > > > from the
> > > > > > > > > local/sessionStore and pass them to the AJAX calls as
> > > > > needed.
> > > > > > > > >
> > > > > > > > > Gili
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > On 2016-06-08 7:40 PM, Trenton D. Adams wrote:
> > > > > > > > > > So are you saying push all the application logic to
> > the
> > > > > > > > > > browser, using javascript?  Are cookies really
> > intended
> > > > > to
> > > > > > > > > > store a whole bunch of user data?
> > > > > > > > > >
> > > > > > > > > > I know with HTML5, you can use
> > > > > > > > > > sessionStorage.setItem("lastname", "last name"). 
> > But,
> > > > > I
> > > > > > > > > > don't think moving most application logic into a
> > > > > browser is
> > > > > > > > > > very maintainable, maybe I'm wrong though.
> > > > > > > > > >
> > > > > > > > > > On Wed, Jun 8, 2016 at 5:29 PM, cowwoc <cowwoc_at_bbs.
> > dark
> > > > > tech.o
> > > > > > > > > > rg> wrote:
> > > > > > > > > > > Without commenting on the specifics of Jersey, I
> > > > > agree:
> > > > > > > > > > > REST is for computers, not humans.
> > > > > > > > > > >
> > > > > > > > > > > I typically expose REST APIs for computers and
> > use
> > > > > cookies
> > > > > > > > > > > to maintain browser sessions. The browser can
> > then
> > > > > read
> > > > > > > > > > > stateful information from the Cookie and serve it
> > to
> > > > > > > > > > > stateless REST APIs. Not all clients are web-
> > > > > browsers, so
> > > > > > > > > > > your REST API should be designed around non-
> > browsers.
> > > > > > > > > > >
> > > > > > > > > > > Gili
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > On 2016-06-08 5:58 PM, Trenton D. Adams wrote:
> > > > > > > > > > > > Good day,
> > > > > > > > > > > >
> > > > > > > > > > > > I'm a bit confused.  I actually have two
> > separate
> > > > > > > > > > > > questions.  I understand that REST is supposed
> > to
> > > > > be done
> > > > > > > > > > > > in a stateless way.  For regular web services
> > > > > that's
> > > > > > > > > > > > easy.  I mean it really shifts a lot of the
> > work to
> > > > > the
> > > > > > > > > > > > client, where it seems to be more difficult to
> > deal
> > > > > with,
> > > > > > > > > > > > but as far as the server goes, it's simple.
> > > > > > > > > > > >
> > > > > > > > > > > > However, how is it even possible to use jersey
> > > > > templates
> > > > > > > > > > > > without state (sessions), in a reasonable way? 
> > The
> > > > > > > > > > > > browser isn't going to maintain the state.  It
> > > > > seems that
> > > > > > > > > > > > one would need to make sure each and every page
> > > > > puts
> > > > > > > > > > > > hidden inputs from the previous form, in the
> > html
> > > > > output,
> > > > > > > > > > > > so that it is re-submitted with the new
> > request. 
> > > > > That
> > > > > > > > > > > > would be a lot of work.  If the user presses
> > the
> > > > > back
> > > > > > > > > > > > button, all that state vanishes, and the user
> > must
> > > > > re-
> > > > > > > > > > > > enter any screens they go forward to again. 
> > This
> > > > > doesn't
> > > > > > > > > > > > make for a very good user experience.
> > > > > > > > > > > >
> > > > > > > > > > > > Can someone explain to me how the use of JAX-RS
> > as
> > > > > an MVC
> > > > > > > > > > > > framework is even possible in a reasonable way,
> > > > > while
> > > > > > > > > > > > being stateless?
> > > > > > > > > > > >
> > > > > > > > > > > > Then, can someone explain to me how
> > statelessness
> > > > > in a
> > > > > > > > > > > > back-end REST web service, promotes good code
> > > > > design,
> > > > > > > > > > > > where user interaction is a necessity?  It
> > seems to
> > > > > me
> > > > > > > > > > > > that the client would then need to maintain all
> > the
> > > > > > > > > > > > state, thereby tightly coupling all the data
> > points
> > > > > > > > > > > > between the different controllers on the
> > client. 
> > > > > > > > > > > > Something like EJB allows you to pass around
> > the
> > > > > stateful
> > > > > > > > > > > > pointer, and you simply add data as you go.
> > > > > > > > > > > >
> > > > > > > > > > > > After reading this stack exchange post, it's
> > > > > sounding
> > > > > > > > > > > > like everyone thinks that REST is NOT for
> > users,
> > > > > but for
> > > > > > > > > > > > services only.
> > > > > > > > > > > > http://stackoverflow.com/questions/3105296/if-r
> > est-
> > > > > applic
> > > > > > > > > > > > ations-are-supposed-to-be-stateless-how-do-you-
> > > > > manage-
> > > > > > > > > > > > sessions
> > > > > > > > > > > >
> > > > > > > > > > > > I understand that it's more scalable, as the
> > server
> > > > > > > > > > > > always knows exactly what you want, because
> > you're
> > > > > > > > > > > > telling it every time.  But it seems like that
> > > > > would come
> > > > > > > > > > > > with a lot more boilerplate coding.
> > > > > > > > > > > >
> > > > > > > > > > > > Thanks.
> > > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > >
> > > > > > >
> > > > >
> > > >
> >