users@jersey.java.net

[Jersey] Re: URI to Resource mapping

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Mon, 27 Aug 2012 11:23:46 +0200

If ResourceContext.matchResource(...) really does not return an injected resource, then it seems like bug in Jersey. Yet, the method will just try to run the matching engine against your URI and return whatever your resource/sub-resource model matches. So if RC.getResource() works ok, the matchResource() should work ok too.

What I don't understand is why you need to use ResourceContext.matchResource(...) method at all. Why don't you just use ResourceContext.getResource()? Your model looks pretty simple and you should be fine just with a class model that contains a bunch of root resources with some sub-resource locator methods that use ResourceContext.getResource(...) to instantiate and inject your sub resources. But, I'm most likely missing the bigger picture of your problem.

In any case, if ResourceContext.matchResource(...) does not properly inject your resource classes, please try to separate the issue into a simple reproducible unit test (or provide a write-up with detailed steps how to reproduce the observed issue) and file a bug against Jersey[1] attaching the unit test or write-up, so that we can evaluate the issue.

Marek

[1] http://java.net/jira/browse/jersey


On Aug 24, 2012, at 7:05 PM, Franck Mangin <franck102_at_yahoo.com> wrote:

> Hi Marek,
>
> Thanks for your reply. I am trying things out, but since I am starting from scratch it is sometimes hard to tell if issues come from unsupported features or from something I overlooked or messed up.
>
> I managed to have injection working fine on subresources (with even a custom Injectable of my own :) ), but I still can't figure out how to navigate from URI to resource (without reimplementing the logic that is already in my locator annotations):
>
> ResourceContext.matchResource(".../bookstore/sections/adventure") returns a SectionResource, but the sectionId has not been injected (it should be "adventure"). My Section constructor looks like this:
>
> public SectionResource(@PathParam("sectionId") String id) { _id = id; }
>
> ... even though that injection works fine in my resource locator:
>
> @Path("sections/{sectionId}")
> public SectionResource locateSection(@Context ResourceContext resourceContext)
> {
> return resourceContext.getResource(SectionResource.class);
> }
>
> Am I missing something? I tried an injectable field instead of the constructor param and I get the same problem.
>
> Thanks!
> Franck
>
>
>
> From: Marek Potociar <marek.potociar_at_oracle.com>
> To: users_at_jersey.java.net
> Sent: Wednesday, August 22, 2012 12:13 PM
> Subject: [Jersey] Re: URI to Resource mapping
>
>
> On Aug 17, 2012, at 4:37 PM, franck102_at_yahoo.com wrote:
>
>> Hi,
>>
>> I am new to Jersey, and struggling to come up with the correct design
>> patterns for my resource hierarchy, especially w.r.t subresources,
>> injection and URIs.
>>
>> I have a fairly simple multi-level hierarchy, let's say bookstore -
>> sections - books and unique IDs for sections & books:
>> /bookstore/sections/adventure
>> /bookstore/sections/adventure/books/some-book-id
>>
>> I have three specific questions:
>>
>> 1. I have a sections resource locator in the bookstore resource with an
>> "sectionID" path param. I have found various versions on the web of the
>> proper code to instantiate the subresource so that it can benefit from
>> injection; including a post mentioning having to use a Scope of
>> "prototype" if more then one subresource is to be instantiated in the
>> request. Most of the posts are pretty old, so I am unclear as to
>> whether they are still valid? Is this pattern the recommended approach:
>>
>> @Path("sections/{sectionId}")
>> public SectionResource getSection(@PathParam("sectionId") String
>> sectionId)
>> {
>> SectionResource res =
>>
>> _resourceContext.getResource(SectionResource.class);
>>
>> res.setId(sectionId);
>> return res;
>> }
>> Is there any way to have the sectionId injected (to avoid the setId
>> call)?
>
> Yes, the story is still valid - you should use an injectable ResourceContext instance to get an instantiated and fully injected resource instance. This means that you may use the @PathParam directly in your SectionResource to inject the "sectionId" value:
>
> @Path("bookstore")
> public class BookStore {
> @Path("sections/{sectionId}")
> public SectionResource getSectionResource(@Context ResourceContext rc) {
> return rc.getResource(SectionResource.class);
> }
> }
>
> public class SectionResource {
> @GET
> public get(@PathParam("sectionId") sectionId) { ... }
> }
>
>> I can't find any documentation about a prototype scope, what is the
>> story there?
>
> I'm not sure I understand what you mean.
>
>>
>> 2. When processing a PUT of a property on a book (e.g. genre) I need to
>> access the book's section model. Would
>> ResourceContext.matchResource(".../bookstore/sections/adventure")
>> return a SectionResource properly initialized for "adventure"? i.e.
>> will it call my locator and set the sectionId?
>> Knowing that the book is a subresource of its section, is there a
>> better way to access the parent resource (other than an explicit
>> setSection in the book's locator)?
>
> Yes. ...why don't you just try it out? :)
>
>>
>> 3. Each book holds a URI to an author resource that lives under
>> /bookstore/authors/some-author.
>> When receiving a PUT request to update the author of a book, can I use
>> ResourceContext.matchResource(<supplied author URI>) to validate that
>> the author exists?
>
> Yes.
>
> Marek
>
>>
>> Any help will be greatly appreciated!
>> Thanks
>
>
>