I've added this to the JSF 2.1 wishlist on <a href="http://seamframework.org">seamframework.org</a><br><br><a href="http://seamframework.org/Documentation/JSF21#H-ReevaluateComponentReferencingMechanismP2">http://seamframework.org/Documentation/JSF21#H-ReevaluateComponentReferencingMechanismP2</a><br>
<br>-Dan<br><br><div class="gmail_quote">On Thu, May 28, 2009 at 2:49 PM, Andy Schwartz <span dir="ltr"><<a href="mailto:andy.schwartz@oraclecom">andy.schwartz@oracle.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hey Alex -<br>
<br>
Alexandr Smirnov wrote On 5/26/2009 5:41 PM ET:<div class="im"><br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
JSF already has a smart enough code that look components by 'id'. Both<br>
<h:outputLabel> and <h:message > use it to lookup target component that<br>
is defined by the 'for' attribute, RichFaces library uses the same<br>
strategy and it works very well. It would be better to use a same code<br>
for <f:ajax> tag instead of simple local/global search.<br>
<br>
<br>
</blockquote>
<br>
<br></div>
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:<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Client identifier of the component for which this element is a label.<br>
</blockquote>
<br>
<br>
Adam logged the following related spec issue on this a couple of years ago:<br>
<br>
<a href="https://javaserverfaces-spec-public.dev.java.net/issues/show_bugcgi?id=266" target="_blank">https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=266</a><br>
<br>
In which Adam says:<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
The Javadoc for UIMessage and TLDDOC for h:message describes it as one that takes a clientId. This was<br>
never the intent - this should always have been a relative ID, exactly as in h:outputLabel. As specified,<br>
h:message is incredibly difficult to use. IMO, this is an errata, not a spec change, though for backwards<br>
compatibility I'd recommend continuing to look for messages in addition as if "for" were for clientIds.<br>
</blockquote>
<br>
<br>
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.)<br>
<br>
Looking at the implementations, MyFaces does the following:<br>
<br>
- Calls findComponent() using the outputLabel/message component as the base component.<br>
- If a component is found, return the id.<br>
- If the component is found, attempt to construct an id manually (via string manipulation).<br>
<br>
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:<br>
<br>
<h:outputLabel for="foo"/><br>
<br>
And:<br>
<br>
<f:ajax execute="foo"/><br>
<br>
Will find the same components when running in MyFaces. (Same goes for the id ":foo").<br>
<br>
Mojarra starts off similar...<br>
<br>
- Calls findComponent() using the outputLabel/message component as the base component.<br>
<br>
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:<br>
<br>
- Walk up the ancestor chain.<br>
- For each component in the ancestor chain, call findComponent().<br>
- 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.<br>
<br>
Umm... Yikes. That's a lot of component tree walking!<br>
<br>
So, a few issues here:<br>
<br>
1. We need a spec clarification<br>
<br>
MyFaces and Mojarra are providing different behaviors... As things currently stand, the following code:<br>
<br>
<f:subview id="bar"><br>
<h:outputLabel for="foo"><br>
</f:subview><br>
<h:inputText id="foo"/><br>
<br>
Is not going to be portable across JSF implementations.<br>
<br>
2. The idea of doing so many findComponent() calls worries me.<br>
<br>
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.<br>
<br>
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:<br>
<br>
- Take the id that we are provided.<br>
- Perform some string manipulation to derive the desired id (eg. append the id to the nearest naming container's client id).<br>
- Return the derived id. (No findComponent() calls).<br>
<br>
Or, if we want to provide diagnostic capabilities:<br>
<br>
- When project stage is development, after we have derived the id, call findComponent() to verify that the referenced component is present.<br>
<br>
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".<br>
<br>
3. We should re-evaluate our component referencing mechanisms for 2.1.<br>
<br>
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).<br>
<br>
Dan mentioned earlier in the thread:<div class="im"><br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
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.<br>
</blockquote>
<br></div>
Not sure what the best solution is, but I agree with Dan that we should take another look at this.<br>
<br>
4. Does <f:ajax> actually need to perform id processing/encoding at render time?<br>
<br>
<f:ajax>/AjaxBehavior currently send all execute/render ids to the client - which means:<br>
<br>
- Lots of findComponent() calls at render time.<br>
- Lots of content bloating.<br>
<br>
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.<br>
<br>
Let's revisit this one 2.1.<br><font color="#888888">
<br>
Andy<br>
</font></blockquote></div><br><br clear="all"><br>-- <br>Dan Allen<br>Senior Software Engineer, Red Hat | Author of Seam in Action<br><br><a href="http://mojavelinux.com">http://mojavelinux.com</a><br><a href="http://mojavelinux.com/seaminaction">http://mojavelinux.com/seaminaction</a><br>
<a href="http://in.relation.to/Bloggers/Dan">http://in.relation.to/Bloggers/Dan</a><br><br>NOTE: While I make a strong effort to keep up with my email on a daily<br>basis, personal or other work matters can sometimes keep me away<br>
from my email. If you contact me, but don't hear back for more than a week,<br>it is very likely that I am excessively backlogged or the message was<br>caught in the spam filters. Please don't hesitate to resend a message if<br>
you feel that it did not reach my attention.<br>