Initializing JAX-RS Sub-resources
Thursday, Apr 4, 2013 |Initializing JAX-RS Sub-resources
Jason Lee 2013-04-04
This is kind of sad to admit (though, surely -- hopefully -- I'm not alone in this :), but I have been initializing subresource manually. For example:
public <T> T getSubResource(Class<T> clazz) {
try {
T resource = clazz.newInstance();
BaseResource br = (BaseResource)resource;
br.uriInfo = uriInfo;
br.securityContext = securityContext;
br.requestHeaders = requestHeaders;
return resource;
} catch (Exception ex) {
throw new WebApplicationException(ex, Status.INTERNAL_SERVER_ERROR);
}
}
While this works, the problems should be pretty obvious: it's extremely inflexible. Fortunately, the JAX-RS Expert Group, who has clearly thought about this more than I, has a better solution: ResourceContext
. Take this example, pulled from the spec:
@Path("widgets")
public class WidgetsResource {
@Context
private ResourceContext rc;
@Path("{id}")
public WidgetResource findWidget(@PathParam("id") String id) {
return rc.initResource(new WidgetResource(id));
}
}
public class WidgetResource {
@Context
private HttpHeaders headers;
public WidgetResource(String id) {...}
@GET
public Widget getDetails() {...}
}
Notice the method WidgetsResource.findWidget()
. The parent resource, WidgetsResource
, has an instance of ResourceContext
injected, which is then used to initialize the subresource instantiated in findWidget()
. The benefit of this approach over the approach above is that everthing is injected, regardless of what I'm expecting to find.
I've been working with JAX-RS for over 3 years now, and I'm just now learning this. Shows that there's always something to learn, and that reading specs pays off. :)