users@jsr311.java.net

URI Contracts

From: Alexander Horn <alex.horn_at_gmail.com>
Date: Mon, 9 Jun 2008 12:21:34 +0200

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