users@jersey.java.net

Re: [Jersey] Re: Hypermedia for JAX-RS/Jersey clients and server

From: Marc Hadley <Marc.Hadley_at_Sun.COM>
Date: Tue, 08 Dec 2009 16:56:08 -0500

On Dec 8, 2009, at 2:34 PM, Marc Hadley wrote:

> On Dec 8, 2009, at 2:08 PM, Santiago Pericas-Geertsen wrote:
>>
>> I want to make sure I understand and can capture all your points:
>>
>> 1) You *don't* think it's a good idea to extend resource representations to include additional meta-data (using Atom or otherwise) such as the following example from RESTfulie:
>>
>> <order>
>> <product>basic rails course</product>
>> <product>RESTful training</product>
>> <atom:link rel="refresh" href="
>> http://www.caelum.com.br/orders/1" xmlns:atom="http://www.w3.org/2005/Atom
>> "/>
>> <atom:link rel="update" href="
>> http://www.caelum.com.br/orders/1" xmlns:atom="http://www.w3.org/2005/Atom
>> "/>
>> <atom:link rel="pay" href="
>> http://www.caelum.com.br/orders/1/pay" xmlns:atom="http://www.w3.org/2005/Atom
>> "/>
>> <atom:link rel="cancel" href="
>> http://www.caelum.com.br/orders/1" xmlns:atom="http://www.w3.org/2005/Atom
>> "/>
>> </order>
>>
> Right. Up till now we've managed to keep JAX-RS at quite a meta-level and I don't think we should be in the business of defining what applications representations have to contain.
>
>>
>> 2) You'd prefer the use of HTTP headers to convey meta-data
>>
> Either headers or something like WADL that describes the links already available in representations. E.g. the information in the RESTfulie representation above could be split into data and metadata something like this:
>
> Link: <http://www.caelum.com.br/orders/1>; rel=refresh
> Link: <http://www.caelum.com.br/orders/1>; rel=update
> Link: <http://www.caelum.com.br/orders/1/pay>; rel=pay
> Link: <http://www.caelum.com.br/orders/1>; rel=cancel
>
> <order>
> <product>basic rails course</product>
> <product>RESTful training</product>
> </order>
>
BTW, I think it likely that existing representations could include URIs so its equally important to be able to ascribe state transition semantics to those without having to change the format of the representation.

Marc.

>> 3) You agree that clients should discover this meta-data dynamically, rather than encode it statically
>>
> Yes.
>
>> 4) You think clients should work in all cases, even if meta-data is not available at runtime?
>>
> I think they should fall back gracefully. Obviously the less metadata available, the less "friendly" the client can be and the more knowledge the user will need to set up requests properly and interpret responses.
>
> Marc.
>
>>
>> On Dec 8, 2009, at 9:42 AM, Marc Hadley wrote:
>>
>>> On Dec 7, 2009, at 3:35 PM, Santiago Pericas-Geertsen wrote:
>>>>
>>>> Thanks for the pointers to your blog and for elaborating your ideas. I can see how this can be useful for tooling and for improving ease of use.
>>>>
>>>> I'm putting together a wiki with some .next ideas for REST [1]. Most of which are being discussed in blogs and papers by other authors. The section entitled "The Need for Better Client APIs" in that wiki outlines some of the goals for a .next client API that the majority of the community seems to agree on (there may be a few more that I have missed).
>>>>
>>>> I believe that your proposal addresses (2) in that list quite well and also gets us closer to (1) and (3). My thoughts on (1) are the following:
>>>>
>>>> i) At its core JAX-RS defines a mapping between URI operations and resource methods. This mapping is dynamic and guided by annotations in server-side resource classes.
>>>>
>>>> ii) The proxy based client APIs that are being proposed define a mapping between resource methods and URI operations (the inverse of (i)). As proposed, the mapping is dynamic and guided by annotations in client-side resource classes (or interfaces).
>>>>
>>>> Given the importance of server evolution, (ii) has to be thought out carefully to avoid excessive coupling. This is key to enable (1).
>>>>
>>>> Instead of using annotations on client-side resource classes to guide the mapping, I wonder if it's possible to use dynamic information obtained from the server. This would clearly enable the server to evolve more freely. Moreover, this relates to (3) given that resource transitions (as in HATEOAS) should ideally be handled in the same way. That is, perhaps all the interactions between clients and servers can be based on these resource transitions.
>>>>
>>>> Following the HATEAOS constraint, every resource representation returns a set of transitions (some of which may be self transitions, causing the server to transitions back to the same state). Other than with the root resource, client developers interact with resources using these transitions (which means they must know at least a subset of them statically even if they don't know how they map to URI operations) without relying on additional static information such as that conveyed by client-side annotations. That is, the client runtime will map proxy calls to URI operations based on information it received from the server rather than information already known to the client.
>>>>
>>>> I realize there's a lot to be fleshed out here :) What do you think so far?
>>>>
>>> I think its important that whatever we come up with will work with existing representation formats. IOW, I don't think we should try to define representation markup that must be present in an entity body in order for the client API to work. Rather I think the client-side should be working with a set of metadata that either contains the links themselves (e.g. HTTP Link headers) or identifies links within the representations and associates them with state transitions. Any client-side infrastructure should be generally useful and not require JAX-RS server-side.
>>>
>>> Marc.
>>>
>>>
>>>>
>>>> [1] http://wikis.sun.com/display/Jersey/Hypermedia+and+Client+APIs
>>>>
>>>> On Dec 4, 2009, at 1:45 PM, gerard davison wrote:
>>>>
>>>>>>
>>>>>>> JDeveloper is a kinda of 3-4GL tool so some of our users need quite a bit of guidance. We knew we wanted something that looked and worked like JSR 311 rather than the generator Marc up together for the wadl project so as Paul will tell you I have been playing with various ideas with a dynamic Proxy. Of course that led to me playing with HATEOAS as with all things restful in general but I am not just focused on the client side that is just where I started playing about.
>>>>>>
>>>>>> Is it fair to say that what you have in mind now is similar to RESTeasy's client framework [1]?
>>>>>
>>>>> Yes, but for example RESTeasy doesn't, at least in the documentation, appear to support sub resources correctly. Not that it took a lot of work to implement it. Also specifically I want proxies and resource classes to be able to be persisted as first class elements via JAX-B. Some of my current thoughts are here; but that doesn't really cover the sever side yet. Not had time to write those up.
>>>>>
>>>>> http://kingsfleet.blogspot.com/2009/09/javalangreflectproxy-client-based-on.html
>>>>> http://kingsfleet.blogspot.com/2009/10/proxy-client-based-on-jersey-with-bit.html
>>>>>
>>>>> The other fun things you can do with proxies is allow the user to control of specific parts of the API. For example if you edit the interface to be:
>>>>>
>>>>> {
>>>>> @GET
>>>>> public Future<Bean> getBean()
>>>>> }
>>>>>
>>>>> You can intuit that the user want an async interface, or indeed to please Jeanfrancois you could do the following to give a simple long pooling interface:
>>>>>
>>>>> {
>>>>> @GET
>>>>> Iterator<Future<Bean>> getBean();
>>>>> }
>>>>>
>>>>> Or I guess following on from the Links/Header discussion over the last few days, though be aware that I probably haven't thought his one through enough.
>>>>>
>>>>> public interface GenericNexus<Entity, Resource>
>>>>> {
>>>>> public Entity getBean();
>>>>> public Resource getSelf()
>>>>> }
>>>>>
>>>>>
>>>>> public interface GenericDeleteResource
>>>>> {
>>>>> @DELETE
>>>>> public Reponse.Status delete();
>>>>> }
>>>>>
>>>>> public interface BeanNexus
>>>>> extends GenericNexus<Bean, BeanResource>
>>>>> {
>>>>>
>>>>> @LinkHeader(rel="next");
>>>>> public BeanResource getNextBean();
>>>>> @LinkHeader(rel="last");
>>>>> public BeanResource getLastBean();
>>>>>
>>>>> @LinkHeader(rel="delete");
>>>>> public GenericDeleteResource delete();
>>>>>
>>>>> }
>>>>>
>>>>> public interface BeanResource
>>>>> {
>>>>> @GET
>>>>> BeanNexus getBean();
>>>>> }
>>>>>
>>>>> //
>>>>>
>>>>> BeanResource br = ...;
>>>>> BeanNexus bn = br.getBean();
>>>>> Bean bean = bn.getEntity();
>>>>> BeanResource = bn.getNextBean();
>>>>>
>>>>>
>>>>> I guess the thing about proxies is that if you can describe a java interface with a reasonable pattern you can quite easily implement that functionality on the back end.
>>>>>
>>>>> Gerard
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>