Promising. As I am just starting to architect a new app that needs a
strong formal ReST interface, I am particularly interested in this.

Question; In your example you have a query link without arguments. How
are those supposed to be provided? (Gosh I need to read up on this
again...)



Cheers
Niclas

On Thu, Oct 13, 2011 at 12:13 PM, Rickard Öberg <[email protected]> wrote:
> Hi,
>
> (WARNING: Longish email on how to do REST properly)
>
> Based on my experience with REST API design in Streamflow, I want to
> investigate a redesign of how we do REST client and server libraries,
> specifically in order to enable Level 3 REST API's, meaning full support for
> hypermedia to drive state transitions in an application.
>
> The server part has already been reasonably explored in Streamflow, and the
> result is that use cases should be exposed, rather than the traditional
> domain objects. This makes it possible to make the client very very thin,
> and all business rules remain on the server where they belong. The current
> REST library code in Git relies on DCI being used, but I intend to factor
> this out so that you can choose to do the traditional "service+anemic
> domain" if you want to. The main point is to support exposing REST resources
> that focus on use cases and hypermedia, whether or not DCI is used.
>
> On the client, I 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:
> 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:
> crc.onResource( new ResultHandler<Resource>()
> {
>    @Override
>    public void handleResult( Resource result, ContextResourceClient client )
>    {
>        // This may throw IAE if no link with relation
>        // "querywithoutvalue" is found in the Resource
>        client.query( "querywithoutvalue", null );
>    }
> } ).
> onQuery( "querywithoutvalue", TestResult.class, new
> ResultHandler<TestResult>()
> {
>    @Override
>    public void handleResult( TestResult result, ContextResourceClient client
> )
>    {
>        Assert.assertThat( result.xyz().get(), CoreMatchers.equalTo( "bar" )
> );
>    }
> } );
>
> crc.refresh();
> ---
> 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:
> // Create Restlet client and bookmark Reference
> Client client = new Client( Protocol.HTTP );
> Reference ref = new Reference( "http://localhost:8888/"; );
> ContextResourceClientFactory contextResourceClientFactory =
> module.newObject( ContextResourceClientFactory.class, client, new
> NullResponseHandler() );
> contextResourceClientFactory.setAcceptedMediaTypes(
> MediaType.APPLICATION_JSON );
>
> // Handle logins
> contextResourceClientFactory.setErrorHandler( new ErrorHandler().onError(
> ErrorHandler.AUTHENTICATION_REQUIRED, new ResponseHandler()
> {
>    // Only try to login once
>    boolean tried = false;
>
>    @Override
>    public void handleResponse( Response response, ContextResourceClient
> client )
>    {
>            // If we have already tried to login, fail!
>            if (tried)
>                throw new ResourceException( response.getStatus() );
>
>            tried = true;
>            client.getContextResourceClientFactory().getInfo().setUser( new
> User("rickard", "secret") );
>
>            // Try again
>            client.refresh();
>    }
> } ).onError( ErrorHandler.RECOVERABLE_ERROR, new ResponseHandler()
> {
>    @Override
>    public void handleResponse( Response response, ContextResourceClient
> client )
>    {
>        // Try to restart this scenario
>        client.refresh();
>    }
> } ) );
>
> crc = contextResourceClientFactory.newClient( ref );
> ---
> 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 Qi4j, 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 Qi4j REST apps.
>
> Thoughts on that?
>
> /Rickard
>
> _______________________________________________
> qi4j-dev mailing list
> [email protected]
> http://lists.ops4j.org/mailman/listinfo/qi4j-dev
>



-- 
Niclas Hedhman, Software Developer
http://www.qi4j.org - New Energy for Java

I live here; http://tinyurl.com/3xugrbk
I work here; http://tinyurl.com/6a2pl4j
I relax here; http://tinyurl.com/2cgsug

_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev

Reply via email to