Elliot thinks JSR-311, JAX-RS: The Java API for RESTful Web Services isn't really that RESTful at all, so the name should be changed to something along the lines of "Java HTTP Server API". Initially, I thought no way, but I think Elliot may be on to something.
I've done a little bit of playing around with Jersey, and I've found the annotations to be quite helpful in building a RESTful interface to our domain objects. Here, for example, are the relevant bits of our UsersResource class which sits the behind the /users uri:
@UriTemplate("/users")
public class UsersResource {
@HttpContext
private UriInfo uriInfo;
private FormatterFactory formatterFactory = new DefaultUserFormatterFactory(); // Spring injected
private RealmManager realmManager = RealmManager.instance(); // Spring injected
@HttpMethod("GET")
@ProduceMime("application/json")
public JSONObject getUsersAsJsonArray() throws JSONException {
JsonFormatter formatter = formatterFactory.getSummaryFormatter();
JSONObject o = new JSONObject();
JSONArray objectArray = new JSONArray();
Search search = new Search(createFilter());
search.setFilter(filter);
realmManager.execute(search);
for (Object item : search.getResults()) {
objectArray.put(formatter.format(uriInfo, item));
}
o.put("totalCount", search.getTotal());
o.put("users", objectArray);
return o;
}
@UriTemplate("{username}")
public UserResource getUser(@UriParam("username") String username) {
User user = realmManager.getUser(username);
if (null == user) {
throw new WebApplicationException(new RuntimeException("user '" + username + "' does not exist."), 404);
}
return new UserResource(formatterFactory, uriInfo, user);
}
private UserFilter createFilter() {
UserFilter filter = new UserFilter();
// Populate a filter using uri parameters
try {
MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters();
for (Map.Entry<String, List<String>> entry : queryParameters.entrySet()) {
String value = entry.getValue().get(0);
PropertyUtils.setSimpleProperty(filter, entry.getKey(), value);
}
} catch (IllegalAccessException e) {
throw new WebApplicationException(e);
} catch (InvocationTargetException e) {
throw new WebApplicationException(e);
} catch (NoSuchMethodException e) {
// ignore - this is a parameter that doesn't match a setter on the filter
}
return filter;
}
}
I've bolded that JAX-RS annotations. Is there anything there that is REST specific? Not really. It is mostly uri munging. Then again, you could also say the same of REST when it gets down to the nuts and bolts of implementation.
On the other hand, REST is more than just uri munging - it is an architectural style, and Elliot is right when he says:
An API is probably the wrong place to enforce architectural decisions
Comments
You can follow this conversation by subscribing to the comment feed for this post.