Consuming ReST services has become a common task, but resource creation is a somewhat more complex task. (Disclaimer : I won’t introduce new concepts, I’m only trying to gather information concerning resource creation).
Resource creation : POST or PUT ?
First question : to create a new resource, should I use a PUT ?
Well, you must ask yourself : Who is responsible for generating the resource id ?
The client provides the ID ? Use a PUT
When using a PUT, the provided URI gives the ID.
$ curl -XPUT 'http://localhost:8080/restservice/resources/42' -d '{ "name" : "mybeautifulresource" }'
The server provides the ID ? Use a POST
When using a POST, it’s up to the server to provide the ID.
$ curl -XPOST 'http://localhost:8080/restservice/resources' -d '{ "name" : "mybeautifulresource" }'
But ? Where is the ID ? Well … in the server response (for instance, Location: gives you the resource URI)
HTTP/1.1 201 - Created Server: Pouet server v.1.02 Location: http://localhost:8080/restservice/resources/42 ... { "id" : "42", "name" : "mybeautifulresource" }
Response content
In the response, some fields may be useful for the client.
- Location, provides the resource URI
- The ETag matching the version of this resource enables client-side caching.
- The Content-Type and the content provides the resource itself
Let’s add those fields, with JAX-RS :
@Context UriInfo uriInfo; ... @PUT @Path("{id}") @Consumes("application/json") public Response addResource(@PathParam("id") String id, Data inputdata) { ... return Response.created(uriInfo.getRequestUri()) .tag(Integer.toString(newResource.hashCode())) .entity(newResource) .type(MediaType.APPLICATION_JSON_TYPE) .build(); }
OK, now I want to use this ETag field correctly
You have to check the client-provided ETag (“If-None-Match” field in the client request) against your server resource. Your server should return the content only if the resource has changed.
The request object can check this tag using the evaluatePreconditions method.
If the provided ResponseBuilder is null, you must return the resource content. Else, you can return the built response.
@GET @Path("{id}") public Response getApp(@PathParam("id") String id, @Context Request request) { Data resource = fetchData(id); EntityTag etag = new EntityTag(Integer.toString(resource.hashCode())); Response.ResponseBuilder builder = request.evaluatePreconditions(etag); if (builder == null) { builder = Response.ok(resource); builder.tag(etag); } return builder.build(); }
Now it’s up to you
Be First to Comment