Skip to main content

JSR 311: Java API for RESTful Web Services

Posted by mhadley on February 14, 2007 at 1:10 PM PST

I was planning to wait until after the ballot to blog this but it seems lots of folks have already noticed and blogged about it so I figure I might as well put my 2p in now.

Reaction so far has been mixed, ranging from "cool... I hope they don't screw it up" through "please ask Sun to reconsider this proposal" so I thought I'd try to address a couple of the negative perceptions noted so far.

The API will be overly abstract/generic
HTTP is the target of this API, we went back and forth a bit on the name and in the end decided to use RESTful in there to highlight that it will focus on RESTful use of HTTP. It doesn't mean we plan to develop an abstract REST API with a binding to HTTP.
The API will presume developers are incompetent
This one seems to come from this sentence in the JSR submission: "Correct implementation requires a high level of HTTP knowledge on the developer's part." OK, perhaps this wasn't put very well, but the plan is to offer default implementations of things like content negotiation and precondition support to save developers having to implement those things themselves (unless they really want to).

A couple of people also complained that the JSR wasn't very specific and didn't include much in the way of detail. JSRs are like that, they describe the problem not the solution. FWIW, here's the sort of thing I currently have in mind though, of course, the final APIs will probably be very different following expert group discussions.

@UriTemplate("widgets/{widgetid}")
@ConsumeMime("application/widgets+xml")
@ProduceMime("application/widgets+xml")
public class Widget {

  @HttpMethod(GET)
  public Representation getWidget(@UriParam("widgetid") String id) {
    String replyStr = getWidgetAsXml(id);
    return new StringRepresentation(replyStr,
      "application/widgets+xml");
  }
 
  @HttpMethod(PUT)
  public void updateWidget(@UriParam("widgetid") String id,
    Representation<Source> update) {
    updateWidgetFromXml(id, update);
  }
 
  @LastModified
  public Date getChangeDate(@UriParam("widgetid") String id) {
    return getLastChanged(id);
  }
}

The above is a resource with a URI of {prefix}/widgets/{widgetid} where {prefix} is the base URI that depends on where the resource is deployed and {widgetId} is a URI template variable that varies for each widget. The resource can produce representations using the application/widgets+xml media type and can also accept updates using the same format. The API runtime would do the work of identifying the correct class for an inbound request based on the URI, the HTTP method, the media type of any request entity and the desired format of the response. The API runtime would also arrange for responses to have a Last-Modified header and provides precondition support based on the output of the getChangeDate method.

Related Topics >>