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