users@jax-rs-spec.java.net

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

From: Sergey Beryozkin <sberyozkin_at_talend.com>
Date: Tue, 15 May 2012 13:02:40 +0100

See comments below:
On 15/05/12 12:49, Marek Potociar wrote:
>
> On May 15, 2012, at 11:20 AM, Sergey Beryozkin wrote:
>
>> I meant that it was under the application *control*
>> to specify which sub-resource locator is about to manage the invocation.
>>
>> Tough luck ? I guess it is if the spec lead believes that for the
>> application code having no idea how the subresource locator is
>> instantiated and selected is a good idea.
>
> I'm not sure I follow. Sub-resource locators are there from v1.0. What
> do you mean when you say that I believe that it is a good idea for the
> application code be clueless about how the SRL is selected and
> instantiated? When did I say anything like that? The whole time here
> everything I have said so far is in fact *exactly* opposite.
>
> Just to reiterate, I am saying that application code should be
> responsible for selecting, instantiation and initialization of the sub
> resource locator instance. Thus I believe that providing the app
> developer with a utility to manually inject the SRL instances is
> preferred approach to any proxy-based or otherwise magical solution.
>
>>
>> The lakmus test is this : can one understand, by looking at the
>> application code, what is actually going on ? This proposed approach
>> goes against the JAX-RS application programming model. Simpler and
>> more convenient ? I wish it was...
>
> What is difficult to understand on this?
>
> @Path("sub/{type}")
> public MyLocator locate(@PathParam String type, @Context ResourceContext
> ctx) {
> switch (type) {
> case "A":
> // requires injection
> return ctx.inject(MyLocatorImplA.class);

When I look at this code I've no idea how MyLocatorImplA is created, is
it a singleton, per-request, pulled up from some instance pool.

Well, this kind of pattern is wide-spread, but what I'm finding
difficult to get is that this kind of pattern will be introduced into
the JAX-RS application land so that people can save typing a couple of
setters on MyLocatorImpl and instead would have the ability to have
contexts injected into fields but at the cost of having a 'foreign'
entity in the main locator code which does something that the reader of
the code (like me at least) can not easily grasp, at least in the "A" case.

But this is only my opinion...

Sergey

> case "B":
> // requires injection & needs to be instantiated via a factory
> MyLocator locator = MyLocatorImplBFactory.create();
> return ctx.inject(locator);
> }
>
> // default impl does not require injection
> return new DefaultLocatorContractImpl();
> }
>
> Marek
>
>>
>> Cheers, Sergey
>>
>> On 15/05/12 10:10, Marek Potociar wrote:
>>>
>>> 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
>>>>>
>>>
>>
>>
>> --
>> 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