users@jersey.java.net

[Jersey] Re: UriInfo injection at resource initialization time

From: Martynas Jusevicius <martynas.jusevicius_at_gmail.com>
Date: Thu, 10 Mar 2011 14:34:51 +0100

Let me ask this way - how do you check that Resource is a leaf of the
matching Resources tree (per-request)? I.e. request URI matches its
URI template and will not match any of its subresources.

On Thu, Mar 10, 2011 at 2:03 PM, Martin Matula <martin.matula_at_oracle.com> wrote:
> Hi,
> The solution I've attached below should not have the issue you are
> mentioning.
> Regarding your comment:
>>> I think JAX-RS lacks means to retrieve URIs of (matching) resources,
>>> as opposed to request URI.
> It is impossible to do in general. Note the set of URI's matching a resource
> can be infinite.
> Martin
>
> public abstract class AbstractResource {
>    private Individual i;
>    AbstractResource() {
>    }
>
>    AbstractResource(URI uri) {
>        initIndividual(uri);
>    }
>
>    void initIndividual(URI uri) {
>        System.out.println(uri);
>        i = ///
>    }
> }
>
> @Path("/")
> @Singleton
> public class TestRootResource extends AbstractResource {
>    private TestSubResource subResource;
>
>    private synchronized void init(UriInfo uriInfo) {
>        if (subResource == null) {
>            initIndividual(uriInfo.getBaseUri());
>            subResource = new
> TestSubResource(uriInfo.getBaseUriBuilder().path(TestSubResource.PATH).build());
>        }
>    }
>
>    @GET
>    @Produces("text/plain")
>    public String doGet(@Context UriInfo uriInfo) {
>        init(uriInfo);
>        return "TestResource.doGet()";
>    }
>
>    @Path(TestSubResource.PATH)
>    public TestSubResource getSubResource(@Context UriInfo uriInfo) {
>        init(uriInfo);
>        return subResource;
>    }
> }
>
> // no annotations needed here
> public class TestSubResource extends AbstractResource {
>    public static final String PATH = "sub";
>
>    TestSubResource(URI uri) {
>        super(uri);
>    }
>
>    @GET
>    @Produces("text/plain")
>    public String doGet() {
>        return "TestSubResource.doGet()";
>    }
> }
>
>
> On 10.3.2011 13:42, Martynas Jusevicius wrote:
>>
>> Martin,
>>
>> I ran into another issue. As UriInfo in Resource constructors
>> represents request URI and not Resource URI, and it gets passed up the
>> subresource chain, I can only use it for initialization when I know
>> that this is actually the matching Resource (the end of the chain).
>>
>> public Resource(Resource parent, @Context UriInfo uriInfo)
>> {
>>   super(parent);
>>   this.uriInfo = uriInfo;
>>   System.out.println(this + " " + uriInfo.getAbsolutePath());
>>   // do some initialization using absolute Resource URI
>>   // setIndividual(uriInfo.getAbsolutePath());
>> }
>>
>> frontend.controller.resource.FrontPageResource_at_be843c
>> http://localhost:8084/ontologies/sioc/classes/Item
>> frontend.controller.resource.ontology.OntologyListResource_at_c6173f
>> http://localhost:8084/ontologies/sioc/classes/Item
>> frontend.controller.resource.ontology.OntologyResource_at_1698552
>> http://localhost:8084/ontologies/sioc/classes/Item
>> frontend.controller.resource.ontology.OntologyClassListResource_at_974121
>> http://localhost:8084/ontologies/sioc/classes/Item
>> frontend.controller.resource.class_.ClassResource_at_1b7a9c1
>> http://localhost:8084/ontologies/sioc/classes/Item
>>
>> The ClassResource is the one that matches the URI. So would it be a
>> solution to discard the previous constructor calls by checking
>>
>> if (this == uriInfo.getMatchedResources().get(0))
>> setIndividual(uriInfo.getAbsolutePath())
>>
>> But debugging I can't really see if the matching Resource goes into
>> matchedResources, so maybe it's better like this if it doesn't
>>
>> if (!uriInfo.getMatchedResources().contains(this))
>> setIndividual(uriInfo.getAbsolutePath())
>>
>> I hope you get what I mean :)
>>
>> I think JAX-RS lacks means to retrieve URIs of (matching) resources,
>> as opposed to request URI.
>>
>> Martynas
>>
>> On Wed, Mar 9, 2011 at 7:06 PM, Martin Matula<martin.matula_at_oracle.com>
>>  wrote:
>>>
>>> I see, if you have a property with the base uri, then it is probably
>>> easiest
>>> to do everything in the constructor of your root resource.
>>> Martin
>>>
>>> On 9.3.2011 18:59, Martynas Jusevicius wrote:
>>>>
>>>> Thanks.
>>>>
>>>> I would have to do the whole model in one go, because the
>>>> representation methods of the root resource are already going to run
>>>> queries on it.
>>>>
>>>> Do you think it's a better idea than storing base URI in some property
>>>> file and using say ServletContextListener for initialization?
>>>>
>>>> On Wed, Mar 9, 2011 at 6:42 PM, Martin Matula<martin.matula_at_oracle.com>
>>>>  wrote:
>>>>>
>>>>> Either you can lazily initialize the Individuals in your resources -
>>>>> i.e.
>>>>> getIndividual() method can take UriInfo as a parameter and can lazily
>>>>> initialize the individual instance variable if it is null, and return
>>>>> its
>>>>> content otherwise (this would have to be in a synchronized block):
>>>>> public abstract class AbstractResource {
>>>>>    private Individual i;
>>>>>
>>>>>    public synchronized Individual getIndividual(UriInfo uriInfo) {
>>>>>        if (i == null) {
>>>>>            i = new Individual(uriInfo.getAbsolutePath());
>>>>>        }
>>>>>        return i;
>>>>>    }
>>>>> }
>>>>>
>>>>> @Path("/")
>>>>> @Singleton
>>>>> public class TestRootResource extends AbstractResource {
>>>>>    @GET
>>>>>    @Produces("text/plain")
>>>>>    public String doGet(@Context UriInfo uriInfo) {
>>>>>        return "TestResource.doGet() - Individual: " +
>>>>> getIndividual(uriInfo);
>>>>>    }
>>>>> }
>>>>>
>>>>> @Path("/sub")
>>>>> @Singleton
>>>>> public class TestSubResource extends AbstractResource {
>>>>>    @GET
>>>>>    @Produces("text/plain")
>>>>>    public String doGet(@Context UriInfo uriInfo) {
>>>>>        return "TestSubResource.doGet() - Individual: " +
>>>>> getIndividual(uriInfo);
>>>>>    }
>>>>> }
>>>>>
>>>>> Or you can do eager initialization of the whole model on the first
>>>>> request
>>>>> and use subresource locators - e.g. this should work:
>>>>>
>>>>> public abstract class AbstractResource {
>>>>>    private Individual i;
>>>>>    AbstractResource() {
>>>>>    }
>>>>>
>>>>>    AbstractResource(URI uri) {
>>>>>        initIndividual(uri);
>>>>>    }
>>>>>
>>>>>    void initIndividual(URI uri) {
>>>>>        System.out.println(uri);
>>>>>        i = ///
>>>>>    }
>>>>> }
>>>>>
>>>>> @Path("/")
>>>>> @Singleton
>>>>> public class TestRootResource extends AbstractResource {
>>>>>    private TestSubResource subResource;
>>>>>
>>>>>    private synchronized void init(UriInfo uriInfo) {
>>>>>        if (subResource == null) {
>>>>>            initIndividual(uriInfo.getAbsolutePath());
>>>>>            subResource = new
>>>>>
>>>>>
>>>>> TestSubResource(uriInfo.getAbsolutePathBuilder().path(TestSubResource.PATH).build());
>>>>>        }
>>>>>    }
>>>>>
>>>>>    @GET
>>>>>    @Produces("text/plain")
>>>>>    public String doGet(@Context UriInfo uriInfo) {
>>>>>        init(uriInfo);
>>>>>        return "TestResource.doGet()";
>>>>>    }
>>>>>
>>>>>    @Path(TestSubResource.PATH)
>>>>>    public TestSubResource getSubResource(@Context UriInfo uriInfo) {
>>>>>        init(uriInfo);
>>>>>        return subResource;
>>>>>    }
>>>>> }
>>>>>
>>>>> // no annotations needed here
>>>>> public class TestSubResource extends AbstractResource {
>>>>>    public static final String PATH = "sub";
>>>>>
>>>>>    TestSubResource(URI uri) {
>>>>>        super(uri);
>>>>>    }
>>>>>
>>>>>    @GET
>>>>>    @Produces("text/plain")
>>>>>    public String doGet() {
>>>>>        return "TestSubResource.doGet()";
>>>>>    }
>>>>> }
>>>>>
>>>>> Hope this helps.
>>>>> Martin
>>>>>
>>>>> On 9.3.2011 18:06, Martynas Jusevicius wrote:
>>>>>>
>>>>>> Sorry Martin, you're right! Base URI was set on each request...
>>>>>>
>>>>>> I was so fixated on getting UriInfo to work and use it to lookup
>>>>>> resources in the RDF model that I forgot that model had to be
>>>>>> initialized in the first place.
>>>>>>
>>>>>> Now I see what you're saying - since I need absolute URIs to
>>>>>> initialize RDF and they cannot be resolved without base URI, this
>>>>>> needs to be done within the request context. This is not even JAX-RS
>>>>>> specific, it's just that I'm implementing RDF and JAX-RS at the same
>>>>>> time..
>>>>>>
>>>>>> And when I have the base URI of the request, I can build an absolute
>>>>>> one using UriBuilder.fromResource(class).build(), right?
>>>>>> The question is, where should I put the initialization? In @GET of the
>>>>>> root Resource and mark it with some flag so it only runs once?
>>>>>> Or is there a better hook for that?
>>>>>>
>>>>>> Martynas
>>>>>>
>>>>>> On Wed, Mar 9, 2011 at 5:01 PM, Martin
>>>>>> Matula<martin.matula_at_oracle.com>
>>>>>>  wrote:
>>>>>>>
>>>>>>> I still don't see how that gets you any more further than
>>>>>>> UriBuilder.fromResource(class).build().
>>>>>>> The root resource needs to figure out the server name, port, context
>>>>>>> path
>>>>>>> and server mapping. How did you get that without the request context?
>>>>>>> If you figured out how to get the "base URI" it for your servlet
>>>>>>> outside
>>>>>>> of
>>>>>>> the request context, you can do the same thing for your JAX-RS
>>>>>>> resources
>>>>>>> and
>>>>>>> then just do
>>>>>>> UriBuilder.fromUri(baseUri).path(Resource.class).build().
>>>>>>> Martin
>>>>>>>
>>>>>>> On 9.3.2011 16:49, Martynas Jusevicius wrote:
>>>>>>>>
>>>>>>>> I had a recursive Resource.getAbsolutePath() which went up the
>>>>>>>> parent
>>>>>>>> tree concatenating getPath().
>>>>>>>>
>>>>>>>> For singletons I could get the URI like this:
>>>>>>>> SearchResource.getInstance().getAbsolutePath().
>>>>>>>>
>>>>>>>> For other Resources the mapping happened within the request.
>>>>>>>>
>>>>>>>> On Wed, Mar 9, 2011 at 4:31 PM, Martin
>>>>>>>> Matula<martin.matula_at_oracle.com>
>>>>>>>>  wrote:
>>>>>>>>>
>>>>>>>>> Hi Martynas,
>>>>>>>>>
>>>>>>>>> On 9.3.2011 15:59, Martynas Jusevicius wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> I had achieved the same using abstract Resource superclass (like
>>>>>>>>>>>> in
>>>>>>>>>>>> my
>>>>>>>>>>>> last example) with
>>>>>>>>>>>> - getPath() and getAbsolutePath() equivalents
>>>>>>>>>>>> - constructor Resource(Resource parent) - effectively building a
>>>>>>>>>>>> parent/child tree of Resource instances
>>>>>>>>>>>> - Servlet-like doGet(), doPost() etc methods
>>>>>>>>>>>> and the real HttpServlet mapping request URIs to Resource
>>>>>>>>>>>> instances
>>>>>>>>>>>> and executing the appropriate do..() methods.
>>>>>>>>>
>>>>>>>>> I mean, how did you get the absolute URI outside of the request
>>>>>>>>> context?
>>>>>>>>> I
>>>>>>>>> am guessing all the above initialization happened upon the first
>>>>>>>>> request
>>>>>>>>> within it's context, no?
>>>>>>>>> Martin
>>>>>>>>>
>>>>>>>>>
>