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 13:42:21 +0100

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