users@jax-rs-spec.java.net

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

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Wed, 29 Aug 2012 15:54:19 +0200

On Aug 29, 2012, at 2:47 PM, Bill Burke <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>> 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
>> 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")

>
> 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.

Marek

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