users@jax-rs-spec.java.net

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

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Tue, 15 May 2012 18:41:30 +0200

On May 15, 2012, at 2:02 PM, Sergey Beryozkin wrote:

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

As typical in most injection frameworks that use this kind of constructs, the default scope is "per-lookup", i.e. per request in our case. This would be a default until JAX-RS introduces a way how to define custom scopes for injectable components (e.g. via further DI/CDI integration etc.).

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

Ok, understood.

Marek

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