Root Resources and Sub Resources
The Java class annotated with the @Path annotation represents a root resource class. The JAX-RS application may have more than one root resource class. Each root resource has one or more resource methods handling requests directly or delegating to subresources. Delegating resource methods are called subresource locators. Subresources are like root resource classes in that they can handle the request or delegate further with the exception being that their class-level @Path annotation is ignored during the method resolution. Effectively, the root resource class is a top level handler supporting a specific URI space of the RESTful web application. The default lifecycle of the root resource is per-request, that is, a new instance is created during every request. There is a number of options available to turn a root resource into the singleton.
Here is a sample JAX-RS root resource class:
package demo.jaxrs.server;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.UriBuilder;
@Path("/customerservice/")
@Produces("application/xml")
public class CustomerService {
@Context
private UriInfo uriInfo;
@GET
public Customers getCustomers() {
return findAllCustomers();
}
@GET
@Path("{id}")
@Produces({"application/json", "application/json"})
public Customer getCustomer(@PathParam("id") long id) {
return findCustomer(id);
}
@PUT
@Path("{id}")
@Consumes("application/xml")
public Response updateCustomer(@PathParam("id") Long id, Order order) {
// update customer
return Response.ok().build();
}
@POST
public Response addCustomer(Customer customer) {
// Create a new Customer resource and return a Location URI
// pointing to it
// Get the URIBuilder initialized with the base URI. For example,
// if the servlet is listening on http://localhost:8080/webapp
// then the builder will be set to this base URI
UriBuilder builder = uriInfo.getBaseUriBuilder();
// Append the path value which this root resource class uses and
// the id of the new customer
// The newCustomerURI will represent a link to the new customer
// resource.
URI newCustomerURI = builder.path(CustomerService.class).path(
customer.getId()).build();
return Response.status(201).location(newCustomerURI).build();
}
@DELETE
@Path("{id}")
public void deleteCustomer(@PathParam("id") String id) {
// delete the customer
}
@Path("{id}/orders/{orderId}/")
public Order getOrder(@PathParam("id") long customerId,
@PathParam("orderId") long orderId) {
return findCustomer(customerId).getOrder(orderId);
}
private Customers findAllCustomers() {
// find all the customers
}
private Customer findCustomer(long id) {
// find the customer with the given id
}
}
Customer resource class can handle requests with URI containing "/customerservice" path segments. For example, requests with the http://localhost/8080/webapp/customerservice URI and the GET HTTP verb will be handled by the getCustomers() method while requests with the "http://localhost/8080/webapp/customerservice/123" will be handled by one of the methods containing the @Path("{id}") annotation, depending on the HTTP verb such as GET, PUT or DELETE being used.
The getOrder() method is a subresource locator because it has no HTTP verb annotation, only the @Path annotation. The root resource may act as a sub-resource if one of its subresource locators delegates to it. For example, requests with the "http://localhost/8080/webapp/customerservice/123/orders/356/state" URI and the GET HTTP verb will be handled by the Order subresource instance. After the subresource locator getOrder() has returned, the runtime will use the remaining unmatched "/state" path segment to find the matching Order method.