Hi Martynas,
If you insist on singletons, you can still do that if you initialize
them lazily upon the first request, provided you are calling
getIndividual() always in the context of a request.
I don't understand the second part of your e-mail.
Martin
On 9.3.2011 15:14, Martynas Jusevicius wrote:
> Omg it works! By printing out the URI at least.
>
> But don't you agree these resources should be @Singleton in principle?
> What about Application.getSingletons() - is including resource
> instance there the same as declaring it @Singleton? But anyway I don't
> see how I could pass UriInfo to obtain TestResource instance to be
> included there.
>
> 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.
>
> Martynas
>
> On Wed, Mar 9, 2011 at 2:46 PM, Martin Matula<martin.matula_at_oracle.com> wrote:
>> Hi,
>> I think all you need to do is remove the singleton annotation and let
>> Ontology.get() handle the performance optimizations (i.e. if a new instance
>> of an individual is returned, or instances are cached).
>> Martin
>>
>> On 9.3.2011 14:29, Martynas Jusevicius wrote:
>>> Markus& Martin,
>>>
>>> thanks for your help, but although I thought I was getting somewhere,
>>> now I can see that I'm still not...
>>>
>>> First of all, let me clarify -- in RDF environment there are no
>>> "Directory" or "File" Resources. *All* Resources (basically anything
>>> that has a URI) are/can have Individual and therefore must follow the
>>> same interface, and this is easiest achieved by introducing an
>>> abstract superclass which deals with the Individual interface.
>>> Some of these Resources are singletons in the REST sense, some of them
>>> not.
>>>
>>> Let me give a simplified example - in this case Individual is not
>>> implemented (it contains a lot of methods) but simply contained by the
>>> superclass:
>>>
>>> abstract public class Resource // implements Individual
>>> {
>>> private Individual individual = null;
>>>
>>> public Resource(UriInfo uriInfo)
>>> {
>>> System.out.println(uriInfo.getAbsolutePath().toString());
>>> // possible Individual initialization
>>> //setIndividual(Ontology.get(uriInfo.getAbsolutePath());
>>> }
>>>
>>> public Individual getIndividual()
>>> {
>>> return individual;
>>> }
>>>
>>> private void setIndividual(Individual individual)
>>> {
>>> this.individual = individual;
>>> }
>>> }
>>>
>>> Individual has to be instantiated using Resource's absolute URI at
>>> some point, ideally in the superclass constructor.
>>>
>>> Then, there is root TestResource at @Path("") and subresource
>>> TestSubResource at @Path("sub").
>>> Both of them should be singletons, since their path never changes and
>>> only one instance is needed.
>>>
>>> @Path(TestRootResource.PATH)
>>> @Singleton
>>> public class TestRootResource extends Resource
>>> {
>>> public static final String PATH = "";
>>>
>>> public TestRootResource(@Context UriInfo uriInfo)
>>> {
>>> super(uriInfo);
>>> }
>>>
>>> @GET
>>> @Produces("text/plain")
>>> public String doGet()
>>> {
>>> return "TestResource.doGet()";
>>> }
>>>
>>> @Path(TestSubResource.PATH)
>>> public TestSubResource getSubResource(@Context UriInfo uriInfo)
>>> {
>>> return new TestSubResource(uriInfo);
>>> }
>>> }
>>>
>>> @Singleton
>>> public class TestSubResource extends Resource
>>> {
>>> public static final String PATH = "sub";
>>>
>>> TestSubResource(UriInfo uriInfo)
>>> {
>>> super(uriInfo);
>>> }
>>>
>>> @GET
>>> @Produces("text/plain")
>>> public String doGet()
>>> {
>>> return "TestSubResource.doGet()";
>>> }
>>> }
>>>
>>> This is probably closest to what I'd like to achieve, and doesn't seem
>>> that different from Martin's example - but of course it doesn't work
>>> since I get the aforementioned IllegalStateException.
>>>
>>> UriBuilder usage like fromResource(TestSubResource.class).build()
>>> gives me nothing new here, since I just as well can use
>>> TestSubResource.PATH.
>>>
>>> The example seems JAX-RS compliant to me, but can you suggest how this
>>> can be refactored to work with Jersey?
>>> Most importantly, how and where can the absolute URI be extracted and
>>> used to initialize Individual?
>>>
>>> Thanks again,
>>>
>>> Martynas
>>> semantic-web.dk
>>>
>>> On Wed, Mar 9, 2011 at 12:16 PM, Markus Karg<karg_at_quipsy.de> wrote:
>>>>> UriInfo injection in constructor is used in an example in "Overview of
>>>>> JAX-RS 1.0 Features"
>>>>>
>>>>> http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features#OverviewofJAX-RS1.0Features->ConditionalGETsandReturning304%28NotModified%29Responses
>>>>> It also says "Notice that in this example the constructor of a
>>>>> resource class can be used perform actions that may otherwise have to
>>>>> be duplicated to invoked for each resource method".
>>>>> That makes perfect sense to me - but are you saying this wouldn't
>>>>> work in Jersey?
>>>>> I see a good specification/implementation letting me be flexible with
>>>>> my code, instead of making me bend my code to fit it.
>>>> Apparently it is not working in Jersey as you experienced and was
>>>> explained already. See that this functionality is not mandatory by the
>>>> JAX-RS 1.1 specification, so relying on that possibility would bind your
>>>> code to a particular implementation, which is not what you want. If you need
>>>> just a static URI, check Martin's solution. If you need a dynamic URI and do
>>>> insist on getting it injected into the resource, you should file a RFE for
>>>> the upcoming JAX-RS 2.0 standard, because in that case, JAX-RS 2.0 must
>>>> forbid singletons (with all the negative side effects then).
>>>>
>>>>> I had implemented the same functionality with a simple HttpServlet, so
>>>>> I'm still not sure if the transition to JAX-RS is worth the trouble.
>>>> JAX-RS is not in contrast to servlets. Servlets are for doing anything
>>>> you like with http. JAX-RS is for doing explicitly REST. If you need REST,
>>>> you're possibly better off with JAX-RS. If you don't, then I do not see why
>>>> you actually want to use JAX-RS.
>>>>
>>>>>> What is the problem with injecting it at invocation? You could have a
>>>>>> facade resource just creating instances of your resource, passing in
>>>>>> @Context for example.
>>>>> That seems like a workaround, but I could give it a shot. Could you
>>>>> please give an example of what you have in mind?
>>>> Actually it is not a workaround but it is exactly how JAX-RS wants it to
>>>> be like, since a directory is not a plain file and vice versa. It is a
>>>> difference between a resource (= a directory containing files) and its
>>>> content (= a plaint file). So it makes rather sense to have *two* resources:
>>>>
>>>> http://localhost/files<-- The directory
>>>>
>>>> http://localhost/files/123<-- The file (can be sub directory)
>>>>
>>>> "Directory" Resource contains Individuals:
>>>>
>>>> @GET @Path("individuals/{id}")
>>>> public Individual getIndividual(@Context UriInfo uriInfo) {
>>>> return new Individual(uriInfo);
>>>> }
>>>>
>>>> "File" ("Subdirectory") Resource implements Individual:
>>>>
>>>> @GET
>>>> public ChildOfIndividual() {
>>>> return new ChildOfIndividual();
>>>> }
>>>>
>>>> I do neither see that this looks like a workaround nor being in any case
>>>> uncommon in the sense of OOP. See that one is plural (@Path("individuals")),
>>>> while the other is singular (implements Individual), so it obviously are two
>>>> different things.
>>>>
>>>>>> It is possible to make your resource implement your Individual
>>>>>> interface, but you have to take care about the process>>sequence at runtime:
>>>>>> You have no guarantee *when* the constructor of the resource is invoked, as
>>>>>> the JAX-RS spec allows>>providers to use different custom life cycles. So it
>>>>>> is valid in JAX-RS that your constructor receives null for @Context>>since
>>>>>> it might be bound to e. g. @Path("/path") while it got invoked due to a
>>>>>> request upon /path/123. If the resource got>>created per application (as per
>>>>>> JAX-RS spec's default), obviously it wouldn't "see" the trailing "123" (as
>>>>>> it was created>>already at that point in time). But it will "see" trailing
>>>>>> "123" for the field injection, since that happens not at resource>>creation
>>>>>> but at actual invocation. That explains the behaviour you have seen. There
>>>>>> is no pure JAX-RS way to overcome that.
>>>>> Well then JAX-RS doesn't make much sense to me in this case... I think
>>>>> if Resource has a static URI like "/path" (which probably means it is
>>>>> a singleton of a root class) then it should be able to access it at
>>>>> any time (its own URI, not the request URI).
>>>> You can access the static path, just check Martin's mail to get the code
>>>> line.
>>>>
>>>> Regards
>>>> Markus
>>>>
>>>>> -----Original Message-----
>>>>> From: Martynas Jusevicius [mailto:martynas.jusevicius_at_gmail.com]
>>>>> Sent: Mittwoch, 9. März 2011 10:16
>>>>> To: users_at_jersey.java.net
>>>>> Cc: Markus Karg
>>>>> Subject: Re: [Jersey] Re: UriInfo injection at resource initialization
>>>>> time
>>>>>
>>>>> Hey Markus,
>>>>>
>>>>> what if I want getIndividual() as a simple getter, not a resource
>>>>> method?
>>>>>
>>>>> It's not that Resource returns or contains Individuals, in essence
>>>>> Resource *is* (or could be) an Individual as well -- both REST and RDF
>>>>> object, since they share the same URI.
>>>>> I was thinking about making Resource implement Individual interface
>>>>> using the individual field, but that means it should be instantiated
>>>>> at (or right after) construction time - and I couldn't find a JAX-RS
>>>>> solution to that yet. Does that make sense?
>>>>>
>>>>> I can look up Individual using Resource URI - but has to be not null
>>>>> at that time.
>>>>>
>>>>> Martynas
>>>>>
>>>>> On Wed, Mar 9, 2011 at 8:21 AM, Markus Karg<karg_at_quipsy.de> wrote:
>>>>>> Try this one:
>>>>>>
>>>>>> @GET
>>>>>> @Path("individuals")
>>>>>> public Individual getIndividual(@Context UriInfo uriInfo) {
>>>>>> return new Individual(uriInfo);
>>>>>> }
>>>>>>
>>>>>> Regards
>>>>>> Markus
>>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Martynas Jusevicius [mailto:martynas.jusevicius_at_gmail.com]
>>>>>> Sent: Mittwoch, 9. März 2011 02:40
>>>>>> To: users_at_jersey.java.net
>>>>>> Subject: [Jersey] UriInfo injection at resource initialization time
>>>>>>
>>>>>> Hey list,
>>>>>>
>>>>>> I'm new here and would like to start with a question :)
>>>>>>
>>>>>> I have Resource classes implementing JAX-RS, however I also want to
>>>>>> combine it with RDF using Jena API.
>>>>>> Each Resource should have a reference to Individual (RDF resource) -
>>>>>> and they share the same absolute URI.
>>>>>> This is a root Resource class:
>>>>>>
>>>>>> @Path("")
>>>>>> @Singleton
>>>>>> public class TestResource
>>>>>> {
>>>>>> private Individual individual = null;
>>>>>>
>>>>>> ...
>>>>>> }
>>>>>>
>>>>>> This means Individual has to be initiated at some point, and at that
>>>>>> point the Resource needs to know its URI to be able to look up
>>>>>> Individual in the RDF model.
>>>>>>
>>>>>> What I've tried (the code goes inside the TestResource defined above):
>>>>>>
>>>>>> 1. Injected class field
>>>>>>
>>>>>> @Context UriInfo uriInfo;
>>>>>>
>>>>>> public TestResource()
>>>>>> {
>>>>>> System.out.println("TestResource.uriInfo: " + uriInfo);
>>>>>> }
>>>>>>
>>>>>> Doesn't work - returns null
>>>>>>
>>>>>> 2. Injected constructor parameter
>>>>>>
>>>>>> public TestResource(@Context UriInfo uriInfo)
>>>>>> {
>>>>>> System.out.println("TestResource(uriInfo): " + uriInfo);
>>>>>> }
>>>>>>
>>>>>> Doesn't work - I get
>>>>>> java.lang.IllegalStateException
>>>>>> com.sun.jersey.server.impl.ThreadLocalHttpContext.getUriInfo
>>>>>> as described in
>>>>>>
>>>>>> http://jersey.576304.n2.nabble.com/injecting-UriInfo-in-constructor-td4510740.html
>>>>>> Same message suggests "access the reference when a request is in
>>>>>> scope" -- but this is not good enough.
>>>>>>
>>>>>> However constructor param is used in JAX-RS tutorial:
>>>>>>
>>>>>> http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features#OverviewofJAX-RS1.0Features-ConditionalGETsandReturning304%28NotModified%29Responses
>>>>>>
>>>>>> 3. @PostConstruct method
>>>>>>
>>>>>> @PostConstruct
>>>>>> public void init()
>>>>>> {
>>>>>> System.out.println("@PostConstruct UriInfo: " + uriInfo);
>>>>>> }
>>>>>>
>>>>>> Doesn't work - never gets executed
>>>>>>
>>>>>> Am I missing something? It seems as such a common use case - why isn't
>>>>>> there a simple solution?
>>>>>> I see no reason why root Resources with static @Path could not have
>>>>>> access to their UriInfo at any time - their URI is known right from
>>>>>> the start?
>>>>>> And why does @PostConstruct not work? I'm running Tomcat 6.0.26.
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Martynas
>>>>>> semantic-web.dk
>>>>>>