users@jax-rs-spec.java.net

[jax-rs-spec users] [jsr339-experts] Re: Re: Re: Re: Re: Re: Back To DI in Subresources

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Tue, 15 May 2012 11:10:15 +0200

On May 11, 2012, at 10:51 PM, Sergey Beryozkin wrote:

> Hi,
> On 03/05/12 11:34, Marek Potociar wrote:
>>
>> On Apr 27, 2012, at 2:00 PM, Sergey Beryozkin wrote:
>>
>>> Hi Marek
>>>
>>> On 27/04/12 12:27, Marek Potociar wrote:
>>>>
>>>> On Apr 20, 2012, at 10:47 PM, Sergey Beryozkin wrote:
>>>>
>>>>> On 20/04/12 19:34, Marek Potociar wrote:
>>>>>>
>>>>>> On Apr 19, 2012, at 11:01 AM, Sergey Beryozkin wrote:
>>>>>>
>>>>>>> On 17/04/12 16:37, Santiago Pericas-Geertsen wrote:
>>>>>>>>
>>>>>>>> On Apr 17, 2012, at 7:45 AM, Marek Potociar wrote:
>>>>>>>>
>>>>>>>>> There are 2 solutions that I've been thinking about:
>>>>>>>>>
>>>>>>>>> 1. introduce an injectable request-scoped ResourceContext with
>>>>>>>>> methods like inject(Class<?> subresourceClass), inject(Object
>>>>>>>>> subresource)
>>>>>>>>> 2. update the spec to mandate field injection on the sub-resource
>>>>>>>>> instances returned by sub-resource locator.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> So far I am leaning towards #1 as it seems more flexible.
>>>>>>>>>
>>>>>>>>> Any thoughts on the above?
>>>>>>>>
>>>>>>>> Why not both? As you say, (1) is more flexible but (2) is quite
>>>>>>>> convenient.
>>>>>>>>
>>>>>>>
>>>>>>> I don't understand how the sub-resource injection can work at all.
>>>>>>> Lets take an example where a root resource is a singleton.
>>>>>>>
>>>>>>> This root resource can return sub-resource instances. Such instances
>>>>>>> can be created at a per-request basis or may've been pre-allocated
>>>>>>> and are singletons too. Only the root resource knows the rules.
>>>>>>
>>>>>> Again, that's why I am leaning towards #1 as it is more flexible and
>>>>>> lets the parent resource decide whether or not the injection should
>>>>>> be used and how.
>>>>>>>
>>>>>>> How can the runtime make sure that the injection into sub-resources
>>>>>>> is thread-safe ?
>>>>>>
>>>>>> It should not. It should be the responsibility of the parent resource.
>>>>>
>>>>> OK. I may've mis-read the original proposal, sorry if I am.
>>>>>
>>>>> What sort of DI is being discussed here ?
>>>>> I'm saying that something like
>>>>>
>>>>> public RootResource {
>>>>> private SubResource mySubResource;
>>>>> @Path
>>>>> public SubResource getSubResource() {
>>>>> return mySubResource;
>>>>> }
>>>>> }
>>>>>
>>>>> public SubResource {
>>>>> @Context
>>>>> private UriInfo ui;
>>>>> @GET @Produces("text/plain")
>>>>> public String getTest() {
>>>>> return "subresource";
>>>>> }
>>>>> }
>>>>>
>>>>> specifically the injection of UriInfo into SubResource is difficult
>>>>> for the runtime to support because it is not aware of SubResource's
>>>>> lifecycle.
>>>>> You are saying the injection is the responsibility of the parent
>>>>> resource (RootResource), so we can expect SubResource have a UriInfo
>>>>> setter for example. I agree, this is what the spec says now.
>>>>>
>>>>> So, what DI support is actually being discussed in this thread ?
>>>>> Can you please type some code ?
>>>>
>>>> What I have in mind is something like:
>>>>
>>>> @Path("root")
>>>> public class RootResource {
>>>> @Context ResourceContext ctx;
>>>>
>>>> @Path("sub1")
>>>> public SubResource getSubResource() {
>>>> return ctx.inject(SubResource.class); // instantiate& inject
>>>> }
>>>>
>>>> @Path("sub2")
>>>> public SubResource getSubResource() {
>>>> SubResource sr = ... obtain the custom-managed instance somehow ...
>>>> return ctx.inject(sr); // inject the instance
>>>> }
>>>> }
>>>>
>>>> public class SubResource {
>>>> @QueryParam("q") private String query;
>>>> @Context private UriInfo uriInfo;
>>>> ...
>>>> }
>>>>
>>>> In "sub1" case the root resource should be able to ask JAX-RS runtime to
>>>> provide a new injected sub-resource instance. In "sub2" case the
>>>> resource should be able to retrieve the sub-resource instance in a
>>>> custom way, but if it decides that it still wants to inject the
>>>> instance, it should be able to do so. Makes sense?
>>>
>>> Thanks for this example.
>>> I'm sorry but IMHO the "ctx.inject(SubResource.class);" looks very anti-JAXRS to me.
>>>
>>> The application code does not need to be *explicitly* concerned about delegating to the injected contexts for the instantiation& injection of the sub-resource handlers. It kind of mixes the runtime (the *transparent* injection of contexts) and the application concerns.
>>
>> Isn't the sub-resource locator pattern breaking the transparent resource creation and injection already anyway?
>>
>
> Why ? The way sub-resources are located is entirely up to the application. the only thing the runtime does is helps with selecting the right method which will provide a sub-resource instance.
> Can you please elaborate a bit more. ideally with some code example

Not sure we understand each other. I am pointing out that in a sub-resource locator the application has to somehow locate and initialize the right sub resource instance. So there is nothing transparent about that from the app's perspective. Thus I do not see how your earlier transparency argument applies here and why it should apply to injection.

>
>>>
>>> We've a discussion on the CXF list with Jakub Bochenski. He actually also listed the above option but we both agreed that it was not ideal, a bit intrusive, etc.
>>>
>>> Jakub proposed another option, having a concrete no-op or abstract 'look-up' method similar to what is supported in Spring, example,
>>>
>>> abstract SubResource getSubresource();
>>>
>>> which the root resource would call.
>>
>> Interesting idea, however that would require proxy-ing the resource class, which would mean that we would have to introduce special rules in the spec for the resources using this type of lookup constructs. Currently the spec allows root resources to be written in a way that prevents proxy-ing (final class, etc.) Also I am not very keen on the idea of deploying abstract classes as resources.
>>
>>> That seems like a cleaner option for cases where it os really important to get subresources having the internal contexts magically injected.
>>
> Yea, I'm not really fond of the abstract look-ups, but apparently they can be normal no-ops.

Is it me or did you just reply to yourself? :) Or was it a response to my previous comment? In any case, if you say that SRLs can be normal no-ops, you mean that they would return null? How would you distinguish between cases when a null is a real null and when it is a fake null?

>> For me the less magic the better.
> OK
>> Also, the less-clean concept covers more use cases and is less intrusive wrt. spec changes.
>>
>>> Btw, what is the real use case for sub-resources having the contexts injected. In the case of root resources it is needed because the root resources can't get them from anywhere else. In case of sub-resources, why it is deemed problematic to have say 'setUriInfo(UriInfo)' added to such a sub-resource ?
>>
>> Seems to me the problem is about convenience. With setter approach one would need to repeat the field declarations from the sub-resource classes in the parent resource classes (notice the recursion here) and bloat the impl. with a lots of setter boilerplate code. Not to mention the potential dynamic aspect of picking the right sub-resource class. These are the problems we would like to primarily address IIUC.
>>
> Repeating the setters is less convenient but realistically requires a minimum amount of effort, in most cases sub resources need to know UriInfo, possibly HttpHeaders, rarely SecurityContext.
>
> As I said, IMHO JAX-RS coding is all about the application developer making decision in his code, based on the different inputs, such as contexts, other events, etc.
>
> Mixing the runtime and application concerns in one place seems not ideal to me...

Well, tough luck - those are already mixed in the sub-resource locators since JAX-RS 1.0. What we are trying to do here (IIUC) is to make writing the sub-resource locators more convenient for developers.

Marek

>
> Cheers, Sergey
>
>> Marek
>>
>>>
>>> Thanks, Sergey
>>>
>>>
>>>
>>>>
>>>> Marek
>>>>>
>>>>> Cheers, Sergey
>>>>>>
>>>>>> Marek
>>>>>>
>>>>>>>
>>>>>>> Thanks, Sergey
>>>>>>>> -- Santiago
>>>>>>>>
>>>>>>>>>> Hi,
>>>>>>>>>>
>>>>>>>>>> I would like to re-activate the already mentioned issue of lack of
>>>>>>>>>> support of DI in sub-resources.
>>>>>>>>>>
>>>>>>>>>> Usually you are going to separate JAX-RS resources and services into
>>>>>>>>>> separate classes. In that case services are going to be injected into
>>>>>>>>>> resource with @Inject (it works already fine in Java EE 6).
>>>>>>>>>>
>>>>>>>>>> However: usually JAX-RS runtime is navigating from the main Resource
>>>>>>>>>> to the sub-resource class via the @Path annotation.
>>>>>>>>>>
>>>>>>>>>> As developer you are creating a sub-resource using an ordinary "new"
>>>>>>>>>> and a constructor with parameters. The sub-resources instance is no
>>>>>>>>>> more managed and injection is not available.
>>>>>>>>>>
>>>>>>>>>> Proposal: we need a way to pass an instance to a JAX-RS runtime to
>>>>>>>>>> inject dependencies.
>>>>>>>>>>
>>>>>>>>>> Btw. parameterless constructors are not enough - usually you are
>>>>>>>>>> going to pass some context from the main resource to the sub
>>>>>>>>>> resources.
>>>>>>>>>>
>>>>>>>>>> See also: https://java.net/jira/browse/JAX_RS_SPEC-72
>>>>>>>>>>
>>>>>>>>>> thanks,
>>>>>>>>>>
>>>>>>>>>> adam
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Sergey Beryozkin
>>>>>>>
>>>>>>> Talend Community Coders
>>>>>>> http://coders.talend.com/
>>>>>>>
>>>>>>> Blog: http://sberyozkin.blogspot.com
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Sergey Beryozkin
>>>>>
>>>>> Talend Community Coders
>>>>> http://coders.talend.com/
>>>>>
>>>>> Blog: http://sberyozkin.blogspot.com
>>>>
>>>
>>>
>>> --
>>> Sergey Beryozkin
>>>
>>> Talend Community Coders
>>> http://coders.talend.com/
>>>
>>> Blog: http://sberyozkin.blogspot.com
>>