Skip to content

Date archive for: May 2015

ReST service and resource creation

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 :)