The goal of this is to build a Grails application that uses a REST servive as a backend.
The REST endpoint is implemented using RESTEasy from the JBoss guys.I have a “create” endpoint, which takes an object of type “Content”, stores it using its own backend and then returns the URI to the newly created object in the HTTP Location header.
The server looks something like this:
@Path("/")
@Produces("application/json")
@Consumes("application/json")
public class RESTEndpoint {
@POST
@Path("/create")
public Response create(Content content, UriInfo uriInfo) {
Long contentId = contentService.create(content);
URI newURI = uriInfo.getBaseUriBuilder().path("/content/{key}").build(contentId);
return Response.created(newURI).build();
}
The point is that the HTTP response produced by this will set the Location header, but it will NOT contain any body. According to HTTP 1.1 this is perfectly legal:
10.2.2 201 Created The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field. The response SHOULD include an entity containing a list of resource characteristics and location(s) from which the user or user agent can choose the one most appropriate. [...]
So the key phrase is “The response SHOULD include an entity…” but it doesn’t HAVE TO.
But, when we use Grails’ REST client, the following results in an exception from the client:
render withRest(uri: "http://cey-linux:8080/restservice/") {
def resp = post(path : 'create',
body: '{ "content":{"name":"My Content"}}"',
requestContentType: "application/json")
resp.getHeaders("Location")
}
I don’t have the exception handy but will reproduce and paste it here.
To fix this problem, I now send the URI of the new content object in the Location header and in the body of the response:
return Response.created(newURI).type(MediaType.TEXT_PLAIN).entity(newURI).build();
This also makes us compatible with HTTP 1.0, which requires that a body is sent in case of response status 201-Created.
Grails’ REST client doesn’t violate anything. Fundamentally because we don’t ship with a REST client so the REST client you refer to is not Grails’ official one. If you a referring to the Grails REST plugin it may well do, but we (the Grails team) don’t maintain the plugin and a plugin doesn’t necessarily mean Grails itself.
Comment by Graeme Rocher — February 26, 2010 @ 1:20 am
Right, I am referring to the Rest Client Plugin:
http://www.grails.org/plugin/rest
Sorry if I got it confused with Grails’ official code. But wouldn’t it make sense to have an official REST client built in? Or is there any other recommended way to talk to a REST service from within Grails?
Comment by Chris Ey — February 26, 2010 @ 1:40 am
Filed this problem here:
http://jira.codehaus.org/browse/GRAILSPLUGINS-1988
Comment by Chris Ey — February 26, 2010 @ 6:36 pm