[jsr-314-open] Ajax rendering of components among compositions?

Dan Allen dan.j.allen at GMAIL.COM
Thu May 28 17:51:04 EDT 2009


On Thu, May 28, 2009 at 2:49 PM, Andy Schwartz <andy.schwartz at oracle.com>wrote:

> Hey Alex -
>
> Alexandr Smirnov wrote On 5/26/2009 5:41 PM ET:
>
>> JSF already has a smart enough code that look components by 'id'. Both
>> <h:outputLabel> and <h:message > use it to lookup target component that
>> is defined by the 'for' attribute, RichFaces library uses the same
>> strategy and it works very well. It would be better to use a same code
>> for <f:ajax> tag instead of simple local/global search.
>>
>>
>>
>
>
> Good point. I agree that ideally we should be consistent across the various
> cases where component attributes refer to other components by id.  I took a
> closer look at the spec/code for the outputLabel "for" attribute.  The spec
> is unfortunately vague (and possibly incorrect).  The "for" tag doc simply
> says:
>
>  Client identifier of the component for which this element is a label.
>>
>
>
> Adam logged the following related spec issue on this a couple of years ago:
>
> https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=266
>
> In which Adam says:
>
>  The Javadoc for UIMessage and TLDDOC for h:message describes it as one
>> that takes a clientId.  This was
>> never the intent - this should always have been a relative ID, exactly as
>> in h:outputLabel.  As specified,
>> h:message is incredibly difficult to use.  IMO, this is an errata, not a
>> spec change, though for backwards
>> compatibility I'd recommend continuing to look for messages in addition as
>> if "for" were for clientIds.
>>
>
>
> One thing that is odd is that this implies that outputLabel is correctly
> specified, though as far as I can tell, both outputLabel and message share
> the same "for" doc.  (At least the tag doc - perhaps I am missing other doc
> in the spec itself.)
>
> Looking at the implementations, MyFaces does the following:
>
> - Calls findComponent() using the outputLabel/message component as the base
> component.
> - If a component is found, return the id.
> - If the component is found, attempt to construct an id manually (via
> string manipulation).
>
> So, this is pretty much identical to our f:ajax execute/render id behavior,
> at least in the case where the id corresponds to a component that can be
> found in the component tree.  That is:
>
>  <h:outputLabel for="foo"/>
>
> And:
>
>  <f:ajax execute="foo"/>
>
> Will find the same components when running in MyFaces.  (Same goes for the
> id ":foo").
>
> Mojarra starts off similar...
>
> - Calls findComponent() using the outputLabel/message component as the base
> component.
>
> So for cases where a relative id is specified in the same naming container,
> or an absolute id is specified, both <f:ajax> and <h:outputLabel> behave the
> same in Mojarra.  However, in the event that the findComponent() call does
> not find the component, Mojarra then goes on to:
>
> - Walk up the ancestor chain.
> - For each component in the ancestor chain, call findComponent().
> - If we reach the root and still haven't found the matching component,
> recursively walk over the entire component tree looking for
> NamingContainers, and call findComponent on each NamingContainer.
>
> Umm... Yikes.  That's a lot of component tree walking!
>
> So, a few issues here:
>
> 1. We need a spec clarification
>
> MyFaces and Mojarra are providing different behaviors...  As things
> currently stand, the following code:
>
>  <f:subview id="bar">
>   <h:outputLabel for="foo">
>  </f:subview>
>  <h:inputText id="foo"/>
>
> Is not going to be portable across JSF implementations.
>
> 2. The idea of doing so many findComponent() calls worries me.
>
> A case that we should be able to handle efficiently is having an <f:ajax>
> tag attached to a component (eg. an <h:commandButton>) that is being stamped
> out repeatedly (eg. in an <h:data> component).  It is possible that the
> <f:ajax> execute/render lists may contain multiple execute/render ids each.
>  In this case, we would end up doing possibly many findComponent() calls
> each time the component is stamped out - ie. for each row in a table.
>  Perhaps with very small component trees this may be acceptable, but I can
> easily see this becoming inefficient as the size of the component tree
> grows.
>
> Personally I would like to see an approach that optimizes common cases to
> avoid unnecessary findComponent() calls.  For example, there may be cases
> where we could:
>
> - Take the id that we are provided.
> - Perform some string manipulation to derive the desired id (eg. append the
> id to the nearest naming container's client id).
> - Return the derived id.  (No findComponent() calls).
>
> Or, if we want to provide diagnostic capabilities:
>
> - When project stage is development, after we have derived the id, call
> findComponent() to verify that the referenced component is present.
>
> We may not be able to derive ids in this fashion for all case, but it seems
> to me that this should work okay for simple "relative" ids - eg.
>  execute="foo".
>
> 3. We should re-evaluate our component referencing mechanisms for 2.1.
>
> For example, I believe that we should provide a way to explicitly address
> components in ancestor naming containers, rather than rely on an expensive
> implicit search mechanism.  Trinidad provides a way to do this - we use the
> "::" prefix to indicate that we should pop up one level in the naming
> container hierarchy (similar to ".." for directory paths).
>
> Dan mentioned earlier in the thread:
>
>  Frankly, for JSF 2.1, I would like to see us go to an XPath-like syntax
>> (or jQuery) to find components because component IDs in JSF just plain suck.
>>
>
> Not sure what the best solution is, but I agree with Dan that we should
> take another look at this.
>
> 4. Does <f:ajax> actually need to perform id processing/encoding at render
> time?
>
> <f:ajax>/AjaxBehavior currently send all execute/render ids to the client -
> which means:
>
> - Lots of findComponent() calls at render time.
> - Lots of content bloating.
>
> However, as Alex has suggested in the past, this may be unnecessary.
>  Instead of sending these ids back and forth to/from the client, we should
> be able to enhance our Behavior mechanism to give the Behavior that
> triggered a postback the first crack at processing the request...  So, for
> example, this would allow AjaxBehavior to enhance the PartialViewContext's
> execute/render lists early on during the Faces lifecycle (when processing a
> postback).  No need to send the ids to the client at all.  The cost of doing
> this is one extra tree visit, which seems like a reasonable trade-off.
>
> Let's revisit this one 2.1.


+1

The goals, simply put, is to design a syntax and behavior that is intuitive,
consistent, and efficient. After many years of JSF, I have days where I feel
like I am just shooting in the dark trying to hit a component. I think the
source of that confusion comes from the different approach taken by Mojarra
and MyFaces, as you have identified. Now I know why with Mojarra I often get
a "hit" when I wasn't expecting one.

-Dan

-- 
Dan Allen
Senior Software Engineer, Red Hat | Author of Seam in Action

http://mojavelinux.com
http://mojavelinux.com/seaminaction
http://in.relation.to/Bloggers/Dan

NOTE: While I make a strong effort to keep up with my email on a daily
basis, personal or other work matters can sometimes keep me away
from my email. If you contact me, but don't hear back for more than a week,
it is very likely that I am excessively backlogged or the message was
caught in the spam filters.  Please don't hesitate to resend a message if
you feel that it did not reach my attention.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/jsr-314-open-mirror/attachments/20090528/8f072b6a/attachment.html 


More information about the jsr-314-open-mirror mailing list