We developed a client-side proxy framework using JAX-RS annotations with
JBoss's RESTEasy JAX-RS implementation. resteasy.sf.net. A few users
have found it useful.
One thing to note is that an interface can't always be shared by the
client and the server:
* Optional parameters and DefaultValues throw a wrench in things for a
client interface
* The server may be doing complex content negotiation and need a Request
injection.
* The client-proxy interface needs to define explicitly what mime type
it is sending so @ConcumeMime really can only take one parameter. Yeah,
you could programmatically do this, but it sort of defeats the purpose
of defining an interface.
* The server may be returning a typed POJO that can be marshalled. The
client might want an org.w3c.Document object instead.
* Response objects may not translate well as a Client interface. The
client might want a typed object, while the server's API might return a
response and vice versa. We also had to provide our own ClientResponse
interface because Response has no type information associated with it
and the proxy framework would have no idea on how to unmarshal the
request into a desired entity.
Alexander Horn wrote:
> I think you're onto something regarding not using language-specific
> means to describe HTTP/1.1 contracts, for instance. But it could take
> a different form than one might expect. For instance, the
> language-neutral form of URIs could be generated based of a Java
> class. Specifically, "CoolResourceURI" provides type-strong guarantees
> to the REST service development team but it can be equally used to
> express the URI contract in a language-neutral form. So the
> development of a REST service could leverage the Java API but REST
> clients are not restrained by this implementation detail. Effectively,
> the Java API in form of annotations acts as a DSL.
>
> Alex
>
> On Mon, Jun 9, 2008 at 9:34 PM, Marc Hadley <Marc.Hadley_at_sun.com> wrote:
>> We have discussed "contracts" in the past, mostly in relation to a client
>> API but there was disagreement about whether a Java-based contract for a
>> HTTP service was good idea or not. There's a good case to be made that the
>> contract should be explicit (and dynamic) in the representations of the
>> resources themselves (hypertext as the engine of state) rather than being a
>> separate artifact in the form of some kind of IDL shared between client and
>> server.
>>
>> Marc.
>>
>> On Jun 9, 2008, at 6:21 AM, Alexander Horn wrote:
>>
>>> Is it desirable to create API in order to express URI contracts as
>>> first-class citizens?
>>> The goal is to encapsulate the routing details from the actual
>>> operations that need
>>> to be performed for the GET, PUT, DELETE etc. functionality.
>>>
>>> I am not sure if this has been discussed before so I think a short example
>>> might
>>> help to illustrate what I mean.
>>>
>>> Assume the architecture is following a DRY principle with the goal of
>>> separating the REST application into three distinct units: "Common",
>>> "Server", and "Client". Only "Common" should need to know about the
>>> internal URI contract requirements. I follow the conviction that an
>>> API-proposal needs to fit on one piece of page. So let me contrast
>>> JAX-RS' current design with a different approach by given a
>>> code-snippet example. I hope with this post I can get constructive
>>> feedback if this is a desirable design alternative from the one put
>>> forth in JAX-RS.
>>>
>>> Code Snippets:
>>>
>>> == Contract/Commons ==
>>>
>>> /**
>>> * Define a URI contract that has the template {path}/{urn}.
>>> * Example URL: "http://localhost:80/a/path/to/urn:some:document"
>>> */
>>> @UriPattern("{path}/{urn}")
>>> CoolResourceURI implements ResourceURI {
>>>
>>> @Variable("path")
>>> private final String path;
>>>
>>> @Variable("urn", "urn:\\.*")
>>> private final URI urn;
>>>
>>> getPath() {
>>> return path;
>>> }
>>>
>>> getURN() {
>>> return urn;
>>> }
>>>
>>> ...
>>> }
>>>
>>> == Server-Side ==
>>>
>>> /**
>>> * Attach {_at_code CoolResource} servlet to the {_at_code CoolResourceURI}
>>> contract.
>>> */
>>> @UriContract(CoolResourceURI.class)
>>> class CoolResource {
>>>
>>> /**
>>> * Handle {_at_code GET} HTTP/1.1 request for resources that map to
>>> {path}/{urn}
>>> */
>>> get(CoolResourceURI uri) {
>>> // do something with the URI components
>>> // Ex: "/some/path/urn:cool:cow"
>>> // --> path="/some/path", urn="urn:cool:cow"
>>> ...(uri.getPath(), uri.getURN());
>>> }
>>>
>>> ...
>>> }
>>>
>>> == Client-Side ==
>>>
>>> /*
>>> * Send {_at_code GET} HTTP/1.1 request for an URI whose lexical
>>> representation matches the template {path}/{urn}
>>> */
>>> ... = getRestController().get(new CoolResourceURI("/some/path",
>>> "urn:cool:cow"));
>>>
>>>
>>>
>>> Notice how this different design strategy would strengthen the
>>> weakly-typed solution that we currently see in the JSR draft. I tried
>>> to demonstrate an improvement to the API by showing three REST
>>> components that use ResourceURIs (see "CoolResourceURI" as an example)
>>> as a means to encapsulate the URI contract to which the REST service
>>> must adhere.
>>>
>>> Also note how the "CoolResource#get(CoolResourceURI)" method is a
>>> type-strong and an succinct way of saying that only GET HTTP/1.1
>>> requests for a specific URI contract should be fulfilled by the server.
>>> It also acts as a type-strong abstraction layer for each
>>> template variable assignment (i.e. {path}, {urn}).
>>>
>>> Regards,
>>> Alex Horn
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_jsr311.dev.java.net
>>> For additional commands, e-mail: users-help_at_jsr311.dev.java.net
>>>
>> ---
>> Marc Hadley <marc.hadley at sun.com>
>> CTO Office, Sun Microsystems.
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jsr311.dev.java.net
>> For additional commands, e-mail: users-help_at_jsr311.dev.java.net
>>
>>
>
>
>
--
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com