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

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

From: Blake Sullivan <blake.sullivan_at_oracle.com>
Date: Fri, 17 Feb 2012 13:32:54 -0800

Ed,

I don't really agree. We have a usability problem, in that the current
behavior is unexpected. Even if the application developers do realize
they have problems, they run into:
a) The mismatch between what visitTree wants (clientIds) and what they
have (search expressions)
b) Reentrancy problems with visitTree and invokeOnComponent.

I believe that my suggested fix is the correct one, the issues are:
1) It is hard
2) This would almost certainly require yet another round of required
code changes for components that modify the EL Context, just like we did
when we introduced invokeOnComponent() and visitTree().

-- Blake Sullivan

On 2/17/12 1:20 PM, Edward Burns wrote:
> I tried to summarize the discussion on this but it boils down to an
> impedence mismatch between EL and the JSF Java API.
>
>>>>>> On Wed, 17 Aug 2011 20:17:36 -0400, Kito Mann<kito.mann_at_virtua.com> said:
> KM> Section 5.6.2.1 (Implicit Object ELResolver for Facelets and Programmatic
> KM> Access) of the spec states the following:
>
> KM> cc -> the current composite component relative to
> KM> the declaring page in which the expression appears.
>
> KM> Since "current composite component" usually means the current composite
> KM> being processed during a tree traversal, "cc" can return null when it's
> KM> referenced elsewhere (i.e. in an action listener);.
>
> KM> I'm thinking that the "cc" implicit variable should return the parent
> KM> composite component in cases where no "current composite component" is
> KM> available.
>
>>>>>> On Fri, 19 Aug 2011 14:31:14 -0500, Leonardo Uribe<lu4242_at_gmail.com> said:
> LU> I have been thinking about this and it seems the missing part has to
> LU> be with UIComponent.findComponent(String expr).
>
> LU> In theory, findComponent allow us to find a "real" component instance
> LU> using a expression, but when the component is inside a datatable or
> LU> other "iteration" component, the state is bound in some way with the
> LU> generated clientId, which can only be found when the call is put in
> LU> context, that means "we are in a valid row".
>
> LU> But there is no method to get a findComponent expression based on a
> LU> component instance (getFindComponentExpression), or a way to traverse
> LU> the component tree just like with invokeOnComponent or visitTree, but
> LU> passing a "find component expression" as param, instead the clientId.
> LU> Maybe it is possible to create a custom VisitContext based on "find
> LU> component expression", but I have not checked it yet.
>
> The commonly used approach is to call invokeOnComponent() with passing
> in an anonymous inner class that takes action on the found component.
> In this way invokeOnComponent() operates as a context-aware
> findComponent().
>
> KM> Hmm.. Isn't the problem really that the ValueExpression
> KM> implementations have no reference to the component for which they
> KM> were created? If the expression knew which component it was created
> KM> for, it could use that component to find the composite component
> KM> parent (among other things).
>
> B> Maybe I'm misunderstanding this, but how is this different than
> B> accessing any other potentially-EL-bound attribute in JSF? EL-bound
> B> values can only be safely evaluated when the component in question is in
> B> the correct context. This means either:
> B> a) During lifecycle processing
> B> b) During a tree visit callback
> B> c) During an invokeOnComponent callback (which is really just a
> B> degenerate version of b)
>
> B> I agree that this is has always been a major usability problem with JSF,
> B> but that's how JSF is.
>
> KM> The difference here is that the EL variable is "cc". The component is
> KM> simply referring to one of its own properties, not a backing bean, so a
> KM> developer would expect that to work when making an arbitrary call to the
> KM> component.
>
> KM> So, I suppose the question is really whether or not we should support the
> KM> ability to use findComponent() and evaluate the properties outside of a
> KM> tree traversal. I've found that calling UIComponent.pushComponentToEL()
> KM> works in some cases if you call it before accessing the component's
> KM> properties. Perhaps that's the solution -- just manually call that method
> KM> first.
>
> The specification for #{cc} has always been such that it's only useful
> within the<cc:implementation> section. In that usage, it always refers
> to the current composite component. In the case of nested composite
> components this can get a little tricky, but it is still well defined.
>
> I am seeing people suggest that we have some way to make #{cc} useful in
> other contexts. I haven't seen a way to do that cleanly, so I'm going
> to push back on it until I do.
>
> Also on this thread was the sentiment that findOnComponent() doesn't
> handle iterating components. I counter by stating that
> invokeOnComponent() does exactly what we want in this case. If you want
> to take action on a component that is within an iterating component,
> pass an anonymous inner class to invokeOnComponent().
>
> Summary: I can't see what action we can take to make this any easier
> right now, but I'm open to suggestions.
>
> Thanks,
>
> Ed
>