On 10/29/10 11:06 PM, David Geary wrote:
It seems that I am perhaps the only dissenting voice here, but I don't care for this solution. 

To those of us that understand the rationale for removing targets and adding these cc:implements... tags, the new tags make perfect sense. But to the uninitiated, they will be bewildering. What does it mean for a button to "implements action source"? Buttons already implement action source.

Ed also raised this concern.  If we are going to continue on with this approach (and I hope that we do), perhaps we need to come up with less ambiguous names for these tags.


IMO, targets are much easier to understand, and to explain.

I understand the urge to remove the targets attribute based on their OO impurity,

OO purity may be part of it, though I believe that the a bigger reason for focusing on this area is that end users (and even EG members) seem to be having difficulty with our existing APIs.

but I think the solution could use some more thought. There are already too many arcane oddities in JSF, whose rationale is only intuited by high priests, and I hate to see us adding more.

The "high priest" analogy does not present an especially charitable view of what is happening here.  We released an API in JSF 2.0 that users are finding problematic.  Expert group/community members have recognized that this is a problem and are attempting to devise a solution that would be more in line with how our users expect this to work.  Perhaps we are off base in aspects of this solution, but the fact that we are looking to address a problem area is a good thing.  I don't think it is fair to apply the old high priest/ivory tower motif here.

My own take is that a big reason why our end users are having difficulty with our current solution is that it is internally inconsistent.  In some cases implementation tags refer to interface metadata (eg. <composite:insertFacet>).  In other cases interface metadata refers to implementation tags (eg. <composite:actionSource>).  In one case, that in retrospect seems embarrassingly convoluted, we have bi-directional references between interface and implementation: <composite:attribute>, which sometimes uses "targets" and other times is referenced via #{cc.attrs}.

Looking at the tag documentation for the <composite:attribute> "targets" attribute:

If this element has a method-signature attribute, the value of the targets attribute must be interpreted as a space (not tab) separated list of client ids (relative to the top level component) of components within the <composite:implementation> section. Space is used as the delimiter for compatibility with the IDREFS and NMTOKENS data types from the XML Schema. Each entry in the list must be interpreted as the id of an inner component to which the MethodExpression from the composite component tag in the using page must be applied. If this element has a method-signature attribute, but no targets attribute, the value of the name attribute is used as the single entry in the list. If the value of the name attribute is not one of the special values listed in the description of the name attribute, targets (or its derived value) need not correspond to the id of an inner component.

The "name" attribute documentation isn't especially reassuring:

The name of the attribute as it must appear on the composite component tag in the using page. If the value of the name attribute is equal to (without the quotes) “action”, “actionListener”, “validator”, or “valueChangeListener”, the action described in ViewHandler.retargetMethodExpressions() must be taken to handle the attribute. In these cases, the method-signature attribute, if present, must be ignored as its value is derived as described in retargetMethodExpressions().

Seriously??  After reading this, is it any wonder that our users are flailing on this?  If anything in this very extended email discussion reeks of arcane high priestdom-ness, this is it.  Wouldn't life have been simpler for our users if <composite:attribute> had no "targets" attribute whatsoever, no special-casing for the "name" attribute and instead we simply boiled this down to: "use #{cc.attrs} for everything"?

I realize that the <composite:attribute> use case is a bit different from <composite:actionSource>/<composite:valueHolder>/<composite:editableValueHolder> cases, so perhaps it would be sufficient to address the <composite:attribute> insanity and stop there.  However, I do think it is worthwhile to look at the full solution and see whether there is room for additional simplification/consistency.

To me, <composite:actionSource> is not all that different from <composite:facet>.  The <composite:facet> API, like <composite:actionSource>, could have just as easily used a target approach.  Yet we decided to go with this:


<composite:interface>
  <composite:facet name="foo"/>
<composite:interface>

<composite:implementation>
  <bar:someComp>
    <composite:insertFacet name="foo"/>
  </bar:someComp>
</composite:implementation>


Instead of:


<composite:interface>
  <composite:facet name="foo" target="mySomeComp"/>
<composite:interface>

<composite:implementation>
  <bar:someComp id="mySomeComp"/>
</composite:implementation>



Why did we go with <composite:insertFacet> instead of "target"?  Which approach is easier for users?  If we had provided both of these approaches in 2.0, which would users prefer?

In my experience I have found our id-referencing APIs to be a difficult to work with.  Id references can be confusing.  It isn't always clear whether relative or full ids should be used or what location relative ids are relative to.  The presence of naming containers influence the specification of id references in ways that can trip up unsuspecting users.  Id references are fragile and can easily go stale when refactoring content.

I believe that we had the right idea when we went with the <composite:facet>/<composite:insertFacet> design.  This solution provides a simple, clear way for the user to express their intentions without suffering any of the above drawbacks.

While I admit that the <composite:actionSource> case is not identical to <composite:facet>, the similarities seem strong.  If JSF 2.0 had included a <composite:actionSource>/<composite:insert/implements/exposes/whateverActionSource> pair (like <composite:facet>/<composite:insertFacet>) and had not included any notion of "targets", I don't think that our users would have had much difficulty coping with this.  If we had exclusively gone with a "implementation references interface" approach (no references from interface to implementation), I think our users would have been altogether better off.

Of course, we cannot go back and time and undo what we've started in JSF 2.0.  It is less important for us to question whether our original design choices were correct than to decide whether it makes sense to introduce new APIs now.  In my mind, this looks like the proposals that we have been discussion are a step in the right direction.  I like the consistency of this new approach; it allows users to interact with all of our interface metadata in a similar manner.  I am certainly open to discussion on this, and I completely agree that we need to be careful when pondering new APIs.  You are right that it is critical that we avoid unintentionally making life more difficult for our users, not just in this case, but for all of our API decisions.

Andy