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

[jsr344-experts] Re: Referencing composite component attributes in child components outside of a tree traversal

From: Kito Mann <kito.mann_at_virtua.com>
Date: Fri, 17 Feb 2012 09:08:06 -0500

On Thu, Feb 16, 2012 at 12:40 PM, Blake Sullivan
<blake.sullivan_at_oracle.com>wrote:

> On 2/16/12 5:09 AM, Kito Mann wrote:
>
>
>
> On Wed, Feb 15, 2012 at 11:53 PM, Blake Sullivan <
> blake.sullivan_at_oracle.com> wrote:
>
>> Maybe I'm misunderstanding this, but how is this different than
>> accessing any other potentially-EL-bound attribute in JSF? EL-bound values
>> can only be safely evaluated when the component in question is in the
>> correct context. This means either:
>> a) During lifecycle processing
>> b) During a tree visit callback
>> c) During an invokeOnComponent callback (which is really just a
>> degenerate version of b)
>>
>> I agree that this is has always been a major usability problem with JSF,
>> but that's how JSF is. The code below with findComponent() has always been
>> wrong. Programmers should not be calling findComponent() and then
>> attempting to evaluate potentially EL-bound values.
>>
>
> The difference here is that the EL variable is "cc". The component is
> simply referring to one of its own properties, not a backing bean, so a
> developer would expect that to work when making an arbitrary call to the
> component.
>
> Unless this is the composite component implementor's own code, then I
> would argue that when getting a the disabled property in this case:
> 1) How does the caller know that the property is not EL-bound
> 2) How does the caller know that an EL-bound property is only bound to "cc"
> 3) How does the caller know that for a "cc" bound property, the property
> is bound to a property that is not itself EL-bound
> 4) If the caller knows all this, they probably know the actual expression
> in the first place
>

So, I suppose the question is really whether or not we should support the
ability to use findComponent() and evaluate the properties outside of a
tree traversal. I've found that calling UIComponent.pushComponentToEL()
works in some cases if you call it before accessing the component's
properties. Perhaps that's the solution -- just manually call that method
first.

>
>
> -- Blake Sullivan
>
>
>> As a side issue, the differences and uses of clientIds, the id attribute
>> of a components, and what the JSF findComponent documentation calls "search
>> expressions" are extremely important, but poorly understood, as this code
>> shows:
>>
>> HtmlImputText input = (HtmlImputText)facesContext.findComponent(clientId);
>>
>> The Mojarra source is similarly confused in some places.
>>
>
> True --- I understand the distinction, but it is difficult to get
> across.
>
>>
>>
>> -- Blake Sullivan
>>
>>
>> On 2/15/12 8:37 PM, Kito Mann wrote:
>>
>> Does anyone have any thoughts on this issue?
>> ___
>>
>> Kito D. Mann | twitter: kito99 | Author, JSF in Action
>> Virtua, Inc. | http://www.virtua.com | JSF/Java EE training and
>> consulting
>> http://www.JSFCentral.com - JavaServer Faces FAQ, news, and info |
>> twitter: jsfcentral
>> +1 203-404-4848 x3 <%2B1%20203-404-4848%20x3>
>>
>> * Listen to the latest headlines in the JSF and Java EE newscast:
>> http://blogs.jsfcentral.com/roller/editorsdesk/category/JSF+and+Java+EE+Newscast
>> * Sign up for the JSFCentral newsletter:
>> http://oi.vresp.com/?fid=ac048d0e17
>>
>>
>>
>> On Fri, Aug 19, 2011 at 6:11 PM, Kito Mann <kito.mann_at_virtua.com> wrote:
>>
>>>
>>> On Fri, Aug 19, 2011 at 3:31 PM, Leonardo Uribe <lu4242_at_gmail.com>wrote:
>>>
>>>> Hi
>>>>
>>>> I have been thinking about this and it seems the missing part has to
>>>> be with UIComponent.findComponent(String expr).
>>>>
>>>
>>> Hmm.. Isn't the problem really that the ValueExpression implementations
>>> have no reference to the component for which they were created? If the
>>> expression knew which component it was created for, it could use that
>>> component to find the composite component parent (among other things).
>>>
>>> What if the spec said that setValueExpression() must use a
>>> "ComponentMethodExpression" instance that held a reference to the component
>>> for which the expression was created?
>>>
>>>
>>>
>>>> I think it is possible to prevent this problem, doing some
>>>> implementation specific tweaks, but from the user point of view, only
>>>> an alternative like a visitTree receiving a findComponent expression
>>>> is reasonable. It could be good to find some use cases where this
>>>> improvement is useful, to support its addition to the spec.
>>>>
>>>
>>> I ran into this when a client had implemented multi-field validation
>>> inside of a PostValidateEvent listener. The code uses findComponent() to
>>> query the properties of different input controls, and when I switched them
>>> over to composite components, this broke:
>>>
>>> HtmlImputText input =
>>> (HtmlImputText)facesContext.findComponent(clientId);
>>> if (input.isDisabled())
>>> {
>>> ....
>>> }
>>>
>>> (Nevermind the fact that using these types of casts isn't always the
>>> best idea.)
>>>
>>> Now, it so happens that clientId now refers to a composite component
>>> child, whereas before it referred to stand-along HtmlInputText component.
>>> This code now returns false when the #{cc.attrs.disabled} expression
>>> returns true, because cc evaluates to null.
>>>
>>> Even if we don't solve this for 2.2, the spec should mandate that
>>> implementations throw an exception or something in this case. This is
>>> something developers simply won't expect (I was certainly surprised).
>>>
>>>
>>>> regards,
>>>>
>>>> Leonardo Uribe
>>>>
>>>> 2011/8/17 Kito Mann <kito.mann_at_virtua.com>:
>>>> > Hello everyone,
>>>> >
>>>> > I just ran into an issue where #{cc.attrs.property} expressions don't
>>>> work
>>>> > when referenced via properties of child components if they're not
>>>> referenced
>>>> > inside of a tree traversal. More information here:
>>>> > https://issues.apache.org/jira/browse/MYFACES-3283 (happens in both
>>>> MyFaces
>>>> > and Mojarra).
>>>> >
>>>> > Section 5.6.2.1 (Implicit Object ELResolver for Facelets and
>>>> Programmatic
>>>> > Access) of the spec states the following:
>>>> >
>>>> > cc -> the current composite component relative to
>>>> > the declaring page in which the expression appears.
>>>> >
>>>> > Since "current composite component" usually means the current
>>>> composite
>>>> > being processed during a tree traversal, "cc" can return null when
>>>> it's
>>>> > referenced elsewhere (i.e. in an action listener);.
>>>> >
>>>> > I'm thinking that the "cc" implicit variable should return the parent
>>>> > composite component in cases where no "current composite component" is
>>>> > available.
>>>> >
>>>> > Thoughts?
>>>> > ---
>>>> > Kito D. Mann | twitter: kito99 | Author, JSF in Action
>>>> > Virtua, Inc. | http://www.virtua.com | JSF/Java EE training and
>>>> consulting
>>>> > http://www.JSFCentral.com - JavaServer Faces FAQ, news, and info |
>>>> twitter:
>>>> > jsfcentral
>>>> > +1 203-404-4848 x3 <%2B1%20203-404-4848%20x3>
>>>> >
>>>> > * Listen to the latest headlines in the JSF and Java EE
>>>> > newscast:
>>>> http://blogs.jsfcentral.com/roller/editorsdesk/category/JSF+and+Java+EE+Newscast
>>>> > * Keep up with the aftermath of the Oracle/Sun merger:
>>>> > http://www.mergerspeak.com
>>>> >
>>>> >
>>>>
>>>
>>>
>>
>>
>
>