Chapter 14. JAX-RS Resource Locators and Sub Resources

Resource classes can partially process a request and then provide another sub-resource object to process the remainder of the request. For example:
@Path("/")
public class ShoppingStore {

   @Path("/customers/{id}")
   public Customer getCustomer(@PathParam("id") int id) {
      Customer cust = ...; // Find a customer object
      return cust;
   }
}


public class Customer {
   
    @GET
    public String get() {...}

    @Path("/address")
    public String getAddress() {...}

}

Resource methods with a @Path annotation and no HTTP method are considered sub-resource locators. They provide an object that can process the request. In the previous example code, ShoppingStore is a root resource because its class is annotated with @Path. The getCustomer() is a sub-resource locator method.
If the client invoked the following:
GET /customer/123
Then the ShoppingStore.getCustomer() method would be invoked first. This method provides a Customer object that can service the request. The HTTP request will be dispatched to the Customer.get() method. Another example is:
GET /customer/123/address
In this request, again, first the ShoppingStore.getCustomer() method is invoked. A Customer object is returned, and the rest of the request is dispatched to the Customer.getAddress() method.
Another interesting feature of sub-resource locators is that the locator method result is dynamically processed at runtime in order to determine how the request should be dispatched. This means that the ShoppingStore.getCustomer() method does not have to declare any specific type.
@Path("/")
public class ShoppingStore {

   @Path("/customers/{id}")
   public java.lang.Object getCustomer(@PathParam("id") int id) {
      Customer cust = ...; // Find a customer object
      return cust;
   }
}


public class Customer {
   
    @GET
    public String get() {...}

    @Path("/address")
    public String getAddress() {...}

}

In the previous example, getCustomer() returns a java.lang.Object. Per request, at runtime, the JAX-RS server will determine how to dispatch the request based on the object returned by getCustomer(). This can be useful in certain situations.
For example, say you have a class hierarchy for your customers. Customer is the abstract base, and CorporateCustomer and IndividualCustomer are subclasses. In this case, your getCustomer() method might perform a Hibernate polymorphic query without requiring any understanding of the concrete class it queries, or the content returned.
@Path("/")
public class ShoppingStore {

   @Path("/customers/{id}")
   public java.lang.Object getCustomer(@PathParam("id") int id) {
      Customer cust = entityManager.find(Customer.class, id);
      return cust;
   }
}


public class Customer {
   
    @GET
    public String get() {...}

    @Path("/address")
    public String getAddress() {...}

}

public class CorporateCustomer extendsCustomer {
   
    @Path("/businessAddress")
    public String getAddress() {...}

}