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.
}
}
Response
vs. a POJO? Look at my 2 getFizz
methods above. When do I return a Fizz
and when do I return a Response
?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.
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.
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).
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 2getFizz
methods above. When do I return aFizz
and when do I return aResponse
?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With