users@jersey.java.net

Re: [Jersey] Nested hierarchies of arbitrary depth

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Fri, 26 Jun 2009 08:34:30 +0200

On Jun 25, 2009, at 8:31 PM, Craig McClanahan wrote:

> Marc Hadley wrote:
>> On Jun 25, 2009, at 9:45 AM, Christopher Piggott wrote:
>>
>>> What is the best way in jersey to handle hierarchies of arbitrary
>>> depth?
>>
>> Sounds like a "sub-resource locator" is what you are looking for,
>> see:
>>
>> https://jsr311.dev.java.net/nonav/releases/1.0/spec/
>> spec3.html#x3-310003.4.1
>>
>>> For example:
>>>
>>> I have a widget
>>> a widget can have subwidgets
>>> subwidgets can also have subwidgets
>>> subwidgets can have components (but they are the bottom of the tree)
>>>
>>> So I might want to find:
>>> /widget/1212/subwidget/17/component/3414
>>>
>>> or
>>>
>>> /widget/12321/subwidget/235235/subwidget/234525/subwidget/234525/
>>> component/315
>>>
>>> My intuition says that I would do this with a @Path that somehow
>>> delegated to a new instance of the subresource (and so on) as it
>>> went
>>> along, recursively. I just can't quite see how to put it together.
>>>
>> Something along these lines:
>>
>> @Path("widget/{widgetid}")
>> public class WidgetResource {
>>
>> @GET
>> ...
>>
>> @Path("subwidget/{subwidgetid}")
>> SubWidgetResource getSubWidget(@PathParam("subwidgetid") String id)
>> return new SubWidgetResource(id);
>> }
>> }
>>
>> public class SubWidgetResource {
>>
>> @GET
>> ...
>>
>> @Path("subwidget/{subwidgetid}")
>> SubWidgetResource getSubWidget(@PathParam("subwidgetid") String id)
>> return new SubWidgetResource(id);
>> }
>> }
>>
>> Essentially getSubWidget returns a new instance of a resource class
>> to handle the relative path "subwidget/{subwidgetid}" and that can
>> recurse as deep as required.
>>
> I agree with Marc's suggested approach, but would just like to
> highlight one issue that bites a lot of people the first time they
> use sub-resource classes like this ... annotation-based injection
> into the sub-resource class does *not* work on constructor
> parameters or instance variables in the sub-resource class. The
> reason for this is that the container didn't create the new sub-
> resource instance (the locator method did), so it has no way to
> track it's lifecycle or perform the injections.
>
> The pattern I've followed on sub-resource classes is to do what Marc
> did in his example here -- explicitly pass on anything you will need
> as parameters to the sub-resource constructor. (In DI terms, you're
> effectively using constructor injection). That applies not only to
> path parameters (as was the case here), but other things that JAX-RS
> might have injected into the root resource class, but needs to be
> passed on.
>

Also see this:

http://markmail.org/message/bxfrxp6gg4nawbn6

for a possible pattern using DI and ResourceContext.

Paul.