RESTing at ease with JSR 311
REST is a style of designing loosely coupled Web applications that rely on named resources rather than messages. Ingeniously, REST piggybacks on the already validated (and successful, don’t you think, man?) infrastructure of the Web– HTTP. That is, REST leverages aspects of the HTTP protocol such as GET and POST requests. Because it’s REST’s bag, RESTful applications turn out to be quite clean in their API as you don’t spend a lot of time reinventing the wheel– you get a lot for free when leveraging HTTP.
I’ve been keeping my eye on JSR 311 as it seemed to make a lot of sense to leverage attributes given the template-like pattern employed by the Restlet framework. For instance, without attributes (and by correlation, JSR 311, which is supported by a developmental version of the Restlet framework), you are forced to override specific methods in the base framework’s hip Resource class associated with HTTP verbs– public void post(Representation representation) handles HTTP POSTs; what’s more, given that the framework doesn’t actually know if a subclass has implemented a particular method, you must also override the allowPost method in the case of POST.
In fact, leveraging attributes in the case of JSR 311 (or, as previously mentioned, the 1.1 snapshot version of the Restlet framework) is a lot like comparing JUnit 3.8.1 to JUnit 4– the entire framework paradigm is shifted, which has the result of a lot less noise (a.k.a code).
For instance, implementing a GET request via JSR 311 is as easy as leveraging the GET attribute:
@GET
@ProduceMime("text/xml")
public String get() {
Collection<Race> races = Race.findAll();
return this.reporter.racesToXml(races);
}
Note, this code is leveraging Jersey, Sun’s reference implementation of JSR 311 (which recently released version 0.8). What’s more, JSR 311 specifies mime annotations for both requests and responses — for instance, the get method above responds with a mime type of “text/xml” — you can easily specify JSON, etc too.
Handling other requests, such as a POST request is just as easy– just use the corresponding copasetic annotation (for instance @POST). Note too, with mime types, you can specify accepted request types. In the case below, the post method will only accept “text/xml”.
@POST
@ConsumeMime("text/xml")
public Response post(String xml) throws Exception {
long id = this.consumer.createRace(xml);
return Response.created(uriInfo.getBaseUriBuilder().
path(Long.toString(id)).build()).build();
}
Of course, the two method above are related to a particular path or URI– JSR 311 supports the @Path annotation, which interestingly enough, is inheritable such that a method can expand upon a base path specified at the class level. For instance, the method above live in class defined as follows:
@Path("/race")
public class RacesResource {
//...
}
Thus, all exposed RESTful methods will respond to the /race URI (i.e. a HTTP GET to /race will be handled by the get method and a HTTP POST to the /race URI will be handled by the post method (provided the request be of mime type “text/xml”, don’t forget!)). Methods can expand upon the /race URI by providing their own @Path annotation, which will effectively append the specified URI to the base URI.
There are certainly more than a few ways to skin the REST cat in Java, baby– you’ve got, to name a few, Restlets, Grails, 1060 NetKernel, and now JSR 311 via Sun’s Jersey. Each framework comes with its own bells and whistles; nevertheless, JSR 311 and Jersey definitely lower the barrier for building (and deploying) RESTful applications even if they are fairly late to the party.
| Related odds and ends | ||
|---|---|---|
Wednesday 16 Jul 2008 | Software Development
Hi Andy,
I’d like to add a precision. With Restlet API’s Resource class, you are not ‘forced’ to override the
allow*()methods.In fact, there are two levels, the lower one is part of Handler, Resource’s super class:
-
allow*()methods-
handle*()methodsThose are dynamically discovered and invoked. It’s not necessary to override them in subclasses. You can however, support extension HTTP methods like
allowMove()andhandleMove()if needed.The higher level is indeed in the Resource class:
-
is/setReadable()methods used byallowGet(),allowHead()-
is/setModifiable()methods used byallowPost(),allowPut(), etc.-
getVariants()andrepresent(Variant)called byhandleGet()andhandleHead()-
storeRepresentation(Representation)called byhandlePut()-
acceptRepresentation(Representation)called byhandlePost()- etc.
It’s just that by default we forbid modification methods. To change that, just call
setModification(true)in yourResourcesubclass’s constructor.It also allows a finer grained control as some users might have read-only access while other with have modification rights. So, this can’t always be described at developement time like in JSR-311, you might need to actually take a look at the handled request, for example for credentials.
Nice post otherwise!
Best regards,
Jerome
Jerome- thanks for clarifying my comment– indeed, the call to
setModification(true)is exactly what I missed. FYI, keep your eyes peeled for a Restlet tutorial over at IBM developerWorks, baby!One thing that stands out with JSR 311 that is solved with Restlets more easily is Security– do you have insight into security w/respect to JSR 311? Is it something that will eventually make it into the spec or is it just handled by containers and JSR 250?
Hi Andy,
You’re welcome. As for a Restlet tutorial on developerWorks, hmmm… it sounds pretty cool
Regarding JAX-RS security, there is only a SecurityContext interface that can be injected. The responsability for actual authentication and authorization is left to the parent container (Restlet, Servlet, etc.).
https://jsr311.dev.java.net/nonav/releases/0.9/javax/ws/rs/core/SecurityContext.html
Best regards,
Jerome
[...] state transfer (also known as REST, baby) is an approach to designing loosely coupled applications that rely on named resources rather [...]