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.