Aerandir
Aerandir

Reputation: 127

REST Subresource Locators

I am reading through the book RESTful Java with JAX-RS 2.0, 2nd Edition and am struggling to understand how Subresource Locators work, below is a cut-down version of the example provided.

CustomerDatabaseResource class

@Path("/customers")
public class CustomerDatabaseResource {

   @Path("{database}-db")
   public CustomerResource getDatabase(@PathParam("database") String db) {
      // find the instance based on the db parameter
      CustomerResource resource = locateCustomerResource(db);
      return resource;
   }

   protected CustomerResource locateCustomerResource(String db) {
     ...
   }
}

CustomerResource Class

public class CustomerResource {
   private Map<Integer, Customer> customerDB =
                          new ConcurrentHashMap<Integer, Customer>();
   private AtomicInteger idCounter = new AtomicInteger();

   public CustomerResource(Map<Integer, Customer> customerDB)
   {
      this.customerDB = customerDB;
   }

   @GET
   @Path("{id}")
   @Produces("application/xml")
   public StreamingOutput getCustomer(@PathParam("id") int id) {
     ...
   }

So I understand that as a request such as GET /customers/northamerica-db/333 comes in, will first match the expression on the method CustomerDatabaseResource.getDatabase() which based upon the location, will create the correct instance of CustomerResource.

What I don't understand is what happens next...

  1. The instance resource gets returned, but returned to where?

  2. How does the web service know to then match and process the remaining part of the request with the method CustomerResource.getCustomer()? I guess this is because The CustomerDataBaseResource class doesn't have a @GET, but I don't really understand how the transition happens.

  3. Is this specific to RESTEasy?

Upvotes: 3

Views: 2353

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 209012

  1. The instance resource gets returned, but returned to where?

It's get's returned to the request processing engine and continues to look for a matching method (inside the return resource object), just like any other request.

  1. How does the web service know to then match and process the remaining part of the request with the method CustomerResource.getCustomer()? I guess this is because The CustomerDataBaseResource class doesn't have a @GET, but I don't really understand how the transition happens

Resource locators aren't supposed to be annotated with Http Methods. That's how they are known to be locators. Since it is not the resource method to be called, it should not be annotated. Imagine this

public class CustomerResource {
    @PUT
    @Path("{id}")
    public Response updateCustomer(Customer customer) {}
    @POST
    @Path("{id}")
    public Response createCustomer(Customer customer) {}
}

If CustomerDataBaseResource.getDatabase() were to be annotated with an Http method, then we couldn't hit the above methods. All the locator needs is the @Path, and the URI matching will continue starting from that path.

/customers/database-us

Once the CustomerResource is created, if the request uri is /customers/database-us/123, then now the next logical step is to find a matching resource method based on the URI, so will be looking for something annotated with @Path that will match 123. Then the Http method is checked.

  1. Is this specific to RESTEasy?

Going through the jax-rs spec, I don't see anything about sub-resource locators, but Jersey also implements this exact behavior. I've read the book you are referring to, and from what I remember, the author doesn't really get much into anything that is implementation specific, but does mention common feautres that most implementers implemented, that is not part of the spec. Maybe this is one of those things.


UPDATE

So it is in the spec. Go to the link and download the spec. You will find everything under 3.4.1 Sub Resources and some algorithm info for request matching in 3.7.2 Request Matching

Upvotes: 2

Related Questions