Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jersey RESTful Services: Resources & Responses

I see a lot of Jersey-based web services consisting of 1+ WebResources that have 1+ endpoints/methods like so:

package com.myws.fizz;
public class FizzResource {
    @GET
    @Path("/fizz/{id}")
    public Response getFizzById(@PathParam("id") Long id) {
        // ...etc.
    }

    @GET
    @Path("/fizz")
    public Fizz getFizzByFoo(Foo foo) {
        // ...etc.
    }
}

package com.myws.buzz;
public class BuzzResource {
    @POST
    @Path("/buzz")
    public Response createBuzz(Buzz buzz) {
        // ...etc.
    }
}
  • I'm confused with what Jersey considers a "resource". Is there a relationship between a "resource" and a database? A table? A POJO?
  • When do you return a Response vs. a POJO? Look at my 2 getFizz methods above. When do I return a Fizz and when do I return a Response?
like image 668
smeeb Avatar asked Oct 31 '14 01:10

smeeb


People also ask

What is Jersey in RESTful web services?

Jersey is Sun's production quality reference implementation for JSR 311: JAX-RS: The Java API for RESTful Web Services. Jersey implements support for the annotations defined in JSR-311, making it easy for developers to build RESTful web services with Java and the Java JVM.

What is the difference between JAX-RS and Jersey?

JAX-RS is an specification (just a definition) and Jersey is a JAX-RS implementation. Jersey framework is more than the JAX-RS Reference Implementation. Jersey provides its own API that extend the JAX-RS toolkit with additional features and utilities to further simplify RESTful service and client development.

What are the Jersey annotations in REST resource class?

Jersey annotations are runtime annotations, therefore, runtime reflection will generate the helper classes and artifacts for the resource, and then the collection of classes and artifacts will be built into a web application archive (WAR).


1 Answers

The term "Resource" isn't so much just a Jersey term, as it is a REST term. When dealing with REST, we have Resources and Representations. A resource can be anything, and in this context, it is some object located on the server, with a URL location. When a client requests for a resource, we send back a representation of it. You ask:

Is there a relationship between a "resource" and a database? A table? A POJO?

It could be a database (that's a thing). And we could simply represent it as a JSON object with the name of the database. Also it could be a table (that's a thing). And we could represent it as a JSON object with the name and column names. It could be a row in a table, and we could represent that with a JSON object with the column names as the keys and the row values as the JSON values. It could be a web page, an image, whatever. So hopefully you get the point that a resource can be anything. What we send back is its representation.

But the term resource is not just limited to returning something to a client request. The client could also send us a representation of a resource, to say create a new resource (POST) or change an existing resource (PUT). The client may send us a JSON representation of a row (resource) in our database.

When do you return a Response vs. a POJO? Look at my 2 getFizz methods above. When do I return a Fizz and when do I return a Response?

Returning Response allows you to fine tune the Response. When the client make a request, they always get back a response. Responses have headers, and entity bodies. When the return type of the resource method is Fizz, you are saying the entity body type will be a Fizz type. When the method returns, what actually happens is that the Fizz object isn't directly returned to the requesting client, all by itself. Behind the scenes, it gets wrapped in a Response that get's sent back to the client. The framework will set the headers it feels appropriate.

So whether we decide to return a Response or Fizz, it will get wrapped in a Response. And like I said, when we return a Response, it allows us to fine tune the Response, adding our own headers, status codes and such. For example, say someone make a POST. You could do something like

@POST
@Path("/buzz")
@Produces(...)
public Response createBuzz(Buzz buzz, @Context UriInfo uriInfo) {
    int buzzID = // create buzz and get the resource id
    UriBuilder builder = uriInfo.getAbsolutePathBuilder();
    builder.path(Integer.toString(buzzId));  // concatenate the id.
    return Response.created(builder.build()).build();
}

Basically what this does is create the resource, say in the database, and we get a return id. We can use the id to concatenate to the URI to the id, this will be the new resource location. In terms of the Response, .created(...) is saying that the status code should be 201 Created, and the value we pass to the created method is the location of the newly created resource. This location will be set as the Location header in the response. So lets say that the path to the POST request is http://blah.com/buzz. What we would send back is http://blah.com/buzz/100, where 100 is the buzzId, and this complete URL is how we will access the buzz resource say with a GET requesst to a resource method annotated with say @GET @PATH("/buzz/{id}")

In terms of a GET, with a Response, we could do

Fizz newFizz = fizzService.getFizz();
return Response.ok(newFizz).build();  // sends the Fizz as the entity body

This is really not so much different than just returning the newFizz from the method, because we aren't doing anything special with the Response. We're just saying the status code should be 200 OK and attaching the entity body. This is what normally happens with a successful GET request. So if we just return the Fizz, instead of a Response, in the case of a successful GET, the framework will implicitly attach a 200 OK status.

Personally, I prefer to return Responses, because of the fine tuning factor.

like image 193
Paul Samsotha Avatar answered Oct 10 '22 13:10

Paul Samsotha