+1
---
Kito D. Mann -- Author, JavaServer Faces in Action
http://twitter.com/kito99  http://twitter.com/jsfcentral
JSF 2 Seminar Oct 6th: http://www.regonline.com/jsf2seminar
JSF Summit Conference Dec 1st-4th in Orlando: http://www.jsfsummit.com
http://www.JSFCentral.com - JavaServer Faces FAQ, news, and info
+1 203-404-4848 x3


On Tue, Sep 15, 2009 at 6:34 PM, Andy Schwartz <andy.schwartz@oracle.com> wrote:
Ryan, All -

Breaking this topic off into a separate thread, though I am impressed with the length of the "<h:dataTable> binding vs. ui:repeat" thread. :-)

Ryan Lubke wrote:
On 9/7/09 6:06 PM, Andy Schwartz wrote:
Thanks Lincoln.  I haven't had time to debug this, but I have a theory about what might be happening.  In your sample:

<a:editText value="#{cc.attrs.task.text}" rendered="#{!cc.attrs.disabled}">
*<f:actionListener for="submit" action="#{taskController.saveTaskAjax(cc.attrs.story, cc.attrs.task)}" /> *
</a:editText>

We expect "cc" to resolve to the containing composite component (ie. to the <socialpm:taskBlock> component).  I wouldn't be surprised if what is actually happening is that "cc" is  being resolved to the <a:editText> composite component instead.
Yep, that's what is happening.
One reason why I suspect this might be happening is that I know that Ryan has investigated/resolved similar problems not too long ago.
The problem we resolved was the passing of #{cc.attrs} attributes between nested composite components.
For this case, the spec recommends using cc.parent.attrs.story and cc.parent.attrs.task, where parent resolves
to the nearest composite component parent of the current composite component.

I am concerned about this behavior.  It isn't clear to me whether the spec is explicit about this behavior, or whether this is something that happens to fall out of the implementation.  Either way, the current behavior seems counterintuitive to me, and, well... wrong.

My feeling is that when a composite component author uses a #{cc} expression in a composite component implementation, eg:

 <composite:implementation>
  <h:outputText value="#{cc.attrs.value}">
 </composite:implementation>

The correct behavior (the behavior expected by the composite component author) is to resolve the #{cc} expression relative to where the expression is defined - not relative to where it happens to end up in the component tree.  So, for example, I believe that these three uses of the #{cc.attrs.value} expression should all evaluate to the same value:

 <composite:implementation>

  <!-- 1. Expression directly in the implementation -->
  <h:outputText value="#{cc.attrs.value}">

  <!-- 2. Expression in non-composite component facet -->
  <bar:someJavaComposite>
    <f:facet name="someFacet">
      <h:outputText value="#{cc.attrs.value}">
    </f:facet>
  </bar:someJavaComponent>

  <!-- 3. Expression in composite component facet -->
  <foo:someCompositeComponent>
    <f:facet name="someFacet">
      <h:outputText value="#{cc.attrs.value}">
    </f:facet>
  </foo:someCompositeComponent>

 </composite:implementation>

The fact that the #{cc.attrs.value} expression evaluates the same in cases #1 and #2 but not in case #3 is non-obvious and is going to be confusing for our users.  The fact that Lincoln and I were confused about this is a good indication that others will be as well.

I am not happy with the work around of using #cc.parent.attrs, since this means that:

1. The user must recognize that the component in question is a composite component and code the expression differently.  While at the moment it is fairly easy to determine whether a particular component is a composite or not (by looking at the namespace declaration), I think that we should strive to blur these lines rather than reinforce them.  For example, I would like to see the ability to define a single tag library that consists of both composite and non-composite components, making the choice of component implementation more transparent to the user.

2. Once the user has coded the expression in a composite component-specific way, this introduces a dependency on the fact that the component in question is a composite component - a dependency that shouldn't be necessary for this particular case.  Such dependencies inhibit flexibility.  If in the future the provider of the composite component decides to switch to a Java-based component, this will break any code (or EL expression) that assumes that the component is a composite.  We should keep such dependencies to a minimum.

3. This also introduces a subtle dependency on the composite component's implementation.  What if the composite component implementation passes the expression along to yet another nested composite component?  Does the user now need to specify an expression that pops out multiple levels of parents?

While it is certainly trickier to deal with from an implementation perspective, I believe that it is very important that we re-consider the current behavior and consider spec'ing that #{cc} expressions always resolve relative to the context in which they are defined.  I feel that the current behavior violates the principle of least surprise (both Lincoln and I were surprised) and also breaks encapsulation (ie. introduces implementation-specific dependencies).

Leaving aside questions of how we might implement my preferred behavior for the moment...  Does anyone have comments on which behavior makes sense from a spec/end user perspective?

Andy