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: Mon, 19 Dec 2016 23:48:54 -0500

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