users@jax-rs-spec.java.net

[jax-rs-spec users] [jsr339-experts] Re: Re: Re: Re: FYI: ResourceContext API proposed

From: Bill Burke <bburke_at_redhat.com>
Date: Wed, 29 Aug 2012 10:09:16 -0400

On 8/29/2012 9:54 AM, Marek Potociar wrote:
>
> On Aug 29, 2012, at 2:47 PM, Bill Burke <bburke_at_redhat.com
> <mailto:bburke_at_redhat.com>> wrote:
>
>>
>>
>> On 8/29/2012 8:15 AM, Marek Potociar wrote:
>>>
>>> On Aug 28, 2012, at 8:40 PM, Bill Burke <bburke_at_redhat.com
>>> <mailto:bburke_at_redhat.com>
>>> <mailto:bburke_at_redhat.com>> wrote:
>>>
>>>>
>>>>
>>>> On 8/28/2012 12:43 PM, Marek Potociar wrote:
>>>>>
>>>>> In Jersey users typically use it to provision (fully-initialized and
>>>>> properly scoped) sub-resource instances
>>>>
>>>> I just not certain this is a job for JAX-RS.
>>>>
>>>>> , regardless of what container
>>>>> manages each particular instance, using the
>>>>> ResourceContext.getResource(...) method. Another problem the users are
>>>>> facing is that in many cases if a user wants to support more
>>>>> complex URI
>>>>> spaces, it would make a lot of sense to leverage the JAX-RS matching
>>>>> engine to internally "find" a proper resource instance or information
>>>>> about it. For those cases the ResourceContext contains the matchXxx()
>>>>> methods that expose the matching engine to the end user.
>>>>>
>>>>
>>>> I've had the case that we implemeted where users want to do something
>>>> like a Servlet.forward(), but I don't think this is the same thing.
>>>> Can you give some examples of each match method? I'm just not
>>>> understanding how it would be used.
>>>
>>> I'll borrow the example from a recent post on our users forum:
>>>
>>> Let's say you have a bookstore application that let you access books
>>> (book resources) via various URI schemes, e.g.:
>>>
>>> /bookstore/books/{bid}
>>> /bookstore/sections/{section}/books/{sbid}
>>> /bookstore/authors/{author}/books/{abid}
>>> ...
>>>
>>> Ideally, you want to have just a single BooksResource that handles all
>>> these URIs. So from sub-resource locators in your SectionsResource and
>>> AuthorsResource you could use the ResourceContext.matchXxx() methods to
>>> "find" the (properly initialized) instance of BooksResource without
>>> having to know too much about it. All you need to know is the main entry
>>> point to all books and the book ID. E.g.:
>>>
>>> @Path("books/{id}")
>>> public class BooksResource {
>>> ...
>>> BooksResource getBook() { ... }
>>> }
>>>
>>>
>>> @Path("authors")
>>> public class AuthorsResource {
>>> ...
>>> @Path("{author}/books/{abid}")
>>> BooksResource getBook(@Context ResourceContext rc, ...) {
>>> String bookId = ... ; // get the book UID
>>> return
>>> rc.matchResource(UriBuilder.fromResource(BooksResource.class).pathParam("id",
>>> bookId).build());
>>> }
>>> }
>>>
>>
>>
>> It would be much simpler to implement this as:
>>
>> @Path("/books") // ignored by subresource locator
>> public class BooksResource {
>>
>> protected String Author author;
>>
>> public BooksResource () {}
>>
>> public BooksResource(String author) {
>> this.author = author;
>> }
>>
>> @GET
>> public List<Books> getBooks() {
>> if (author != null) {...}
>> else {...}
>> }
>>
>> @Path("{id}")
>> @GET
>> public Book getBook(@PathParam("id") bookId)
>>
>>
>> @Path("/author")
>> public AuthorsResource getAuthor() {
>> return new AuthorsResource();
>> }
>> }
>>
>> @Path("/authors")
>> public class AuthorsResource {
>>
>> @Path("{id}")
>> @GET
>> public Author getAuthor(@PathParam("id")...) {...}
>>
>> ...
>> @Path("{author}/books")
>> BooksResource getBook(@PathParam("author") author) {
>> return new BooksResource(author);
>> }
>> }
>>
>
> You need to take my simplistic example with a grain of salt. In any
> case, what you wrote above demonstrates the problem as the above is
> exactly what users seem to complain about all the time, because:
>
> * they don't want to repeat themselves and inject values into SRL
> methods just to pass the values to the returned sub-resource if
> these could be automatically injected by the framework.
> * the sub-resource may be relying on larger amount of injectable data
> making the case above just worse
> * the scope of the matched resource may be different from the default
> one and the resources can be managed by different containers but
> there is no common API to provide the proper way how to access these
> resources
> * users sometimes just want to match particular URIs to see if there
> are some specific related resources available and based on that
> information decide what to do next, but there's no API that would
> expose the matching engine to the users at the moment so are either
> forced to use the proprietary extensions or implement the matching
> themselves

I don't agree with your assessment on injection. CDI, Spring, Guice, or
EJB could be used just as easily. I don't see why we need an
abstraction for injection especially when CDI exists in Java EE. I
would absolutely support a Servlet.forward() mechanism, but I'm still
not convinced this current feature is a good direction. I'd like to
hear feedback from others, especially Sergey.

I also don't think users would be interested in matching if they had
forward() functionality.

>>> Obviously, you can use those methods to conveniently support URI graphs
>>> - from books resource you could easily navigate to authors or sections
>>> etc. Other, more advanced scenarios are possible too. Among the main
>>> advantages is that you don't need to know too much about the
>>> implementation details and initialization of those other resource and
>>> that you can avoid internal redirects.
>>>
>>
>> I'm not seeing it. Your use case is already supported by the spec and
>> also does not work very well for this:
>>
>> GET /authors/billburke/books
>>
>
> I'm sure you see how the example could be extended to support that...
> e.g. rc.matchResource("books/billburke")
>

No, I don't. How could you keep using the BooksResource class? You
don't have the author information to perform the correct query and build
of the returned book collection.


>>
>> Also, (I'm not sure!) ResourceContext would not be able to have a
>> portable implementation because I don't think you would be able to
>> determine/resolve EJB references.
>
> You're right - this is one of the areas we need to focus on next. We
> need to work with EJB guys to provide standard hooks for EJB lookup.
> Nevertheless, while the solution would not be portable, it would still
> be useful to have it as it unifies the resource lookup API for the
> JAX-RS users and saves them a lot of headache.
>

This may be supported already in CDI Beanmanager. I'll ask my CDI guys.

-- 
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com