jsr372-experts@javaserverfaces-spec-public.java.net

[jsr372-experts] Re: [jsr372-experts mirror] Re: Re: remove final from methods in UIComponent to make them proxyable in CDI

From: Leonardo Uribe <leonardo.uribe_at_irian.at>
Date: Tue, 20 Dec 2016 00:00:50 -0500

Hi

I forgot to say that the trick done in omnifaces ParamExtension with
@ViewTransientScope could be a viable "CDI standard" solution.
I'll try to see what happens.

regards,

Leonardo Uribe

2016-12-19 23:48 GMT-05:00 Leonardo Uribe <leonardo.uribe_at_irian.at>:

> Hi
>
> MR>> If you examine the Javadoc of the current milestone
> MR>> you will see the the final modifiers were removed.
>
> MR>> Note this was done a couple of milestones ago.
>
> I see, thanks Manfred for mention it.
>
> AT>> I think it's just a matter of a CDI scope (Context instance) that
> goes
> AT>> to the current ViewRoot and gets the component from there. The
> AT>> component is then cached in the scope, and the scope is destroyed
> AT>> whenever the component tree is destroyed.
>
> Yes, in fact I created an internal @ViewTransientScope to deal with this
> logic.
>
> AT>> There's no need to save/restore anything or have JSF control
> anything,
> AT>> as the scope just initially calls through to whatever is the current
> AT>> tree.
>
> Yes, the intention of the proxy is avoid any state saving by CDI.
> Components
> still are saved in the component tree, but CDI does not mess with that
> anymore. But the proxy has the logic to extract the component instance from
> the component tree.
>
> AT>> You can usually register your own Bean<T> instances instead. See e.g.
> AT>> what we did for http://showcase.omnifaces.org/cdi/Param or see the
> AT>> managed property test, where we test that e.g. this works:
>
> Interesting trick, I'll take a look to see if we can use a similar solution
> from UIComponents.
>
> AT>> As for the following example:
> AT>> That's not really CDI injection at all, is it? That's more like the
> AT>> component calling a setter on a CDI bean via a value reference.
> That's
> AT>> a rather different thing, almost the reverse.
>
> Yes, the example is not CDI injection. But solve this is really important
> in JSF context, and we can't fix it without a "cooperation" between CDI
> and JSF.
>
> AT>> A CDI centric injection would rather be something like:
>
> @Inject
> @ComponentId("some:id")
> private HtmlInputText name;
>
> AT>> In the first case, you could perhaps try something (out of the spec)
> AT>> using an Interceptor on the setter method the value expression is
> AT>> bound to.
>
> I have not fully analyzed a CDI centric solution, so I do not know how to
> take advantage of Interceptor.
>
> I find a solution like @ComponentId(...) a bit hard to understand. The
> reason
> is the id is not really and id, but a relative search expression, and its
> resolution depends on the context the proxy is injected, which happens in a
> lazy way when the proxy is called by first time.
>
> That explanation sounds too abstract. Suppose the following lines:
>
> public void pressButton(ActionEvent evt) {
> String nameString = (String) name.getValue();
> ...
> }
>
> as soon as getValue() is called, if no previous method from the proxy
> instance is called before this one, the proxy resolution algorithm takes
> place, usually taking as reference a call to UIComponent.
> getCurrentComponent().
> So, the way how @ComponentId is resolved depends on the context the proxy
> is
> called. Now, if we compare that with the "binding" attribute solution,
> "binding" always resolve the right component, because the attribute is set
> on the markup that generates the component tree. But of course "binding"
> "tends to fail in a spectacular way". So you end up with combinations of
> UIComponent.getParent(), UIComponent.getNamingContainer(),
> UIComponent.getCurrentCompositeComponent(), because there is not a Search
> Expression API that helps you find a component using a reference and an
> expression. Something like this:
>
> SearchExpressionHandler handler = facesContext
> .getApplication().getSearchExpressionHandler();
> SearchExpressionContext searchContext =
> SearchExpressionContext.createSearchExpressionContext(context,
> refComponent);
> handler.resolveComponent(searchContext, "main:name", new
> ContextCallback(){
> @Override
> public void invokeContextCallback(FacesContext context,
> UIComponent target)
> {
> //...
> }
> });
>
> @ComponentId looks like a simplification to all that. I like more
> @ResolveComponent(expression), where "expression" can be "some:id" or
> something like that.
>
> Of course, all that is just speculation. The key problem is how to inject
> UIComponent instances creating the right proxy classes with CDI standard,
> which is the missing piece of the puzzle. The problem is you can't add a
> Bean<T> on runtime, and JSF initialization happens way after CDI
> initialization. In that context, I feel fix "binding" attribute more
> appealing and viable.
>
> regards,
>
> Leonardo Uribe
>
> 2016-12-19 17:42 GMT-05:00 arjan tijms <arjan.tijms_at_gmail.com>:
>
>> P.s.
>>
>> As for the following example:
>>
>> @Named
>> @ViewScoped
>> public class CustomBean implements Serializable {
>>
>> private HtmlInputText name; // Injected through "binding" attribute.
>>
>> // ...
>> }
>>
>> That's not really CDI injection at all, is it? That's more like the
>> component calling a setter on a CDI bean via a value reference. That's a
>> rather different thing, almost the reverse.
>>
>> A CDI centric injection would rather be something like:
>>
>> @Named
>> @ViewScoped
>> public class CustomBean implements Serializable {
>>
>> @Inject
>> @ComponentId("some:id")
>> private HtmlInputText name;
>>
>> // ...
>> }
>>
>> In the first case, you could perhaps try something (out of the spec)
>> using an Interceptor on the setter method the value expression is bound to.
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
>>
>>
>>
>> On Mon, Dec 19, 2016 at 11:29 PM, arjan tijms <arjan.tijms_at_gmail.com>
>> wrote:
>>
>>> Hi,
>>>
>>> On Fri, Dec 16, 2016 at 11:40 PM, Leonardo Uribe <
>>> leonardo.uribe_at_irian.at> wrote:
>>>
>>>> There is no doubt UIComponent instances are managed by JSF, because the
>>>> component tree is generated by JSF. That means JSF should be responsible
>>>> of create the component and set it into the CDI Bean.
>>>>
>>>
>>> I think it's just a matter of a CDI scope (Context instance) that goes
>>> to the current ViewRoot and gets the component from there. The component is
>>> then cached in the scope, and the scope is destroyed whenever the component
>>> tree is destroyed.
>>>
>>> There's no need to save/restore anything or have JSF control anything,
>>> as the scope just initially calls through to whatever is the current tree.
>>>
>>>
>>> CDI provide Producer Methods, but these methods does not handle generics,
>>>>
>>>
>>> You can usually register your own Bean<T> instances instead. See e.g.
>>> what we did for http://showcase.omnifaces.org/cdi/Param or see the
>>> managed property test, where we test that e.g. this works:
>>>
>>> @Inject @ManagedProperty("#{param['test']}")
>>> private String testParam;
>>>
>>> @Inject @ManagedProperty("#{managedPropertyBean.myStringMap}")
>>> private Map<String, String> stringMap;
>>>
>>> @Inject @ManagedProperty("#{managedPropertyBean.myIntegerMap}")
>>> private Map<Integer, Integer> integerMap;
>>>
>>> Kind regards,
>>> Arjan Tijms
>>>
>>>
>>>
>>>
>>>
>>>
>>> The table in :
>>>>>
>>>>> http://arjan-tijms.omnifaces.org/p/jsf-23.html#1316
>>>>>
>>>>> The one used in the presentation for JSF 2.3. See the line that says:
>>>>>
>>>>> View #{view} - javax.faces.component.UIViewRoot
>>>>>
>>>>> It should be somewhere in the spec, but I do not have the PDF or know
>>>>> where is in the javadoc.
>>>>>
>>>>> regards,
>>>>>
>>>>> Leonardo Uribe
>>>>>
>>>>>
>>>>>
>>>>> 2016-12-15 18:44 GMT-05:00 Edward Burns <edward.burns_at_oracle.com>:
>>>>>
>>>>>> >>>>> On Thu, 15 Dec 2016 17:10:37 -0500, Leonardo Uribe <
>>>>>> leonardo.uribe_at_irian.at> said:
>>>>>>
>>>>>> LU> 1. Change the table to exclude UIViewRoot from injection.
>>>>>> LU> 2. Do the change removing "final" modifiers and include
>>>>>> UIViewRoot as CDI
>>>>>> LU> injectable, do not inject components for current version.
>>>>>> LU> 3. Do the change and make components injectable.
>>>>>>
>>>>>> 2016-12-15 17:23 GMT-05:00 manfred riem <manfred.riem_at_oracle.com>:
>>>>>>
>>>>>> MR> As previously stated we already did explore this early on in the
>>>>>> 2.3
>>>>>> MR> cycle and have concluded it is too complex for its perceived
>>>>>> MR> benefits.
>>>>>>
>>>>>> >>>>> On Thu, 15 Dec 2016 17:44:39 -0500, Leonardo Uribe <
>>>>>> leonardo.uribe_at_irian.at> said:
>>>>>>
>>>>>> LU> I don't know. Sometimes different persons trying to solve the same
>>>>>> LU> problem can find different solutions.
>>>>>>
>>>>>> LU> The good news is we can make 2 or 3 at any time, even if it is not
>>>>>> LU> now. But as I said, I do not want to throw the towel for include
>>>>>> LU> this in JSF 2.3, not until I do one last push.
>>>>>>
>>>>>> Thanks for making one last push, but this is too scary to re-open. I
>>>>>> recall how messy it quickly got when I tried to do it.
>>>>>>
>>>>>> Manfred for my convenience, please let me know what table to modify
>>>>>> for
>>>>>> Option 1.
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Ed
>>>>>>
>>>>>> --
>>>>>> | edward.burns_at_oracle.com | office: +1 407 458 0017
>>>>>> | 36 business days until DevNexus 2017
>>>>>> | 61 business days until JavaLand 2017
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>