blob: 62245bd5e7de28e14e9ab4d9bddc4636a23eb170 [file] [log] [blame]
///////////////////////////////////////////////////////////////
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
///////////////////////////////////////////////////////////////
[[library-rest-client-primer, HATEOAS Primer]]
= ReST - HATEOAS Primer
The Zestâ„¢ ReST Client implements HATEOAS (Hypermedia As The Engine Of Application State) to the full extent intended
by Roy Fielding. The ReST Client Library enables the creation of HATEOAS applications that are NOT using the URL space,
and it is NOT about doing RPC calls over HTTP using a common exchange format (like JSON).
The <<library-rest-server>> is a corresponding library for creating usecase-driven ReST servers, and with that the
corresponding client becomes very thin, as all business rules remain on the server where they belong.
*The main point is to support exposing REST resources that focus on use cases and hypermedia.*
On the client, we have been thinking a lot about what Roy wrote in his thesis, which boils down to "client makes GET
request, based on relation of link invoked and response (headers+hypermedia) make a decision, and then follow links or
invoke forms to perform state transitions".
It's a state machine.
This is different from your average REST client today in that this model explicitly says that you need to do a GET
first (otherwise you have nothing to react to), that the "rel" of the link you followed is important (otherwise context
is unknown), and that the client should not make assumptions about what comes back (otherwise you cannot deal with
exceptions, on system and application level).
The current REST client approach which is imperative:
[source,java]
--------------
result = client.get(somelink)
--------------
does not allow for any of the above. Instead, the client code should first register handlers for what to do in various
circumstances, and then simply perform one operation: "refresh". This will trigger the first GET to the bookmarked URL,
and after that the handlers will do all the work, based on the result. A handler may continue the work by invoking new
requests, or it may abort. "refresh" does not return any value, and usually does not throw any exceptions.
Example:
[snippet,java]
-----------
source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/docsupport/RestPrimerDocs.java
tag=1
-----------
The client first builds up the set of handlers, and describe what they should react to. The client then invokes
"refresh" which will trigger the first GET on the bookmark URL. This will return a representation of that context as a
Resource, and the handler for that is invoked. This then invokes the link with relation "querywithoutvalue" with no
input (no request parameters needed). The result of that is then handled by another handler, and the invocation of
"refresh" then returns successfully. Note that the first handler may not directly handle the "result" of
client.query("querywithoutvalue, null) as it cannot be assumed what happens next. All you know is that you are
following a link.
On crc (ContextResourceClient) it is also possible to registers handlers that are always applied, such as error
handlers. Here is the setup of crc:
[snippet,java]
-----------
source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/docsupport/RestPrimerDocs.java
tag=2
-----------
These general handlers cover what to do for login and error handling, for example.
In the traditional REST client this is not as easy to do, as you are more or less assuming a "happy path" all the time.
In the above scenario there could be any number of steps between doing "refresh" and getting to the meat of the use
case, such as doing a signup for the website, login, redirects to other servers, error handling and retries, etc.
It becomes possible to blend general application and error handling logic with use case specific handlers.
That's basically it. This is where I want to go with support for REST, as a way to truly leverage the REST ideas and
make it very easy to do REST applications *and* clients based on Zest, by keeping the application logic on the server.
In the long run there would also be a JavaScript version of the client, with the same characteristics, so that you can
easily build a jQuery UI for Zestâ„¢ REST apps.