Reputation: 127
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...
The instance resource
gets returned, but returned to where?
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.
Is this specific to RESTEasy?
Upvotes: 3
Views: 2353
Reputation: 209012
- 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.
- 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 TheCustomerDataBaseResource
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.
- 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