Hi<br><br>Some days ago, it was mentioned on myfaces dev list that &quot;targets&quot;<br>attribute does not seem to work as expected. After review the available<br>documentation and doing some test, my conclusion was the spec is good,<br>
but this part needs a little bit more documentation (and fix some <br>bugs), because there are use cases that are causing problems to users.<br>Some of these problems has been already mentioned (spec issue 755) but<br>my intention here is do a full and detailed analysis. <br>
<br>The property &quot;targets&quot; is used for these tags:<br><br>composite:actionSource<br>composite:editableValueHolder<br>composite:valueHolder<br>composite:clientBehavior<br>composite:attribute<br><br>For the first four cases, this property is used by :<br>
<br>ViewDeclarationLanguage.retargetAttachedObjects(FacesContext context,<br>                                    UIComponent topLevelComponent,<br>                                    List&lt;AttachedObjectHandler&gt; handlers)<br>
<br>In JSF 2.0 rev A it was made explicit the need to handle nested<br>composite component with this lines:<br><br>&quot;... The implementation must support retargeting attached objects from <br>the top level compsite component to targets that are composite and <br>
non-composite components ....&quot;<br><br>This is ok ;-).<br><br>The problem is the description about how composite:attribute &quot;targets&quot; <br>property works does not match with the algorithm for:<br><br>ViewDeclarationLanguage.retargetMethodExpressions(FacesContext context, <br>
                                    UIComponent topLevelComponent)<br><br>Here is the documentation about composite:attribute &quot;targets&quot;:<br><br>&quot;... If this element has a method-signature attribute, <br><br>
the value of the targets attribute must be interpreted as a space <br>(not tab) separated list of client ids (relative to the top level <br>component) of components within the &lt;composite:implementation&gt;  section. <br>
<br>Space is used as the delimiter for compatibility with the IDREFS and <br>NMTOKENS data types from the XML Schema. <br><br>Each entry in the list must be interpreted as the id of an inner <br>component to which the MethodExpression  from the composite component <br>
tag in the using page must be applied. <br><br>If this element has a method-signature attribute, but no targets <br>attribute, the value of the name  attribute is used as the single entry <br>in the list. <br><br>If the value of the name  attribute is not one of the special values <br>
listed in the description of the name attribute, targets  (or its <br>derived value) need not correspond to the id of an inner component ...&quot;.<br><br>At this point everything seems to be ok. But look this documentation<br>
(I&#39;ll put the important points):<br><br>&quot;.....<br> # Get the value of the targets attribute. If the value is a ValueExpression <br>   evaluate it. If there is no targets attribute, let the name of the <br>   metadata element be the evaluated value of the targets attribute.<br>
 # Interpret targets as a space (not tab) separated list of ids. For each entry <br>   in the list:<br>     ......<br>    # If name is equal to the string &quot;action&quot; without the quotes, call <br>      ActionSource2.setActionExpression(javax.el.MethodExpression) on target, <br>
      passing attributeMethodExpression.<br>    # If name is equal to the string &quot;actionListener&quot; without the quotes, call <br>      ActionSource.addActionListener(javax.faces.event.ActionListener) on target, <br>
      passing attributeMethodExpression wrapped in a MethodExpressionActionListener.<br>    # If name is equal to the string &quot;validator&quot; without the quotes, call <br>      EditableValueHolder.addValidator(javax.faces.validator.Validator) on target, <br>
      passing attributeMethodExpression wrapped in a MethodExpressionValidator.<br>    # If name is equal to the string &quot;valueChangeListener&quot; without the quotes, call <br>      EditableValueHolder.addValueChangeListener(javax.faces.event.ValueChangeListener) <br>
      on target, passing attributeMethodExpression wrapped in a <br>      MethodExpressionValueChangeListener.<br>    # Otherwise, assume that the MethodExpression should be placed in the <br>      components attribute set. The runtme must create the MethodExpression <br>
      instance based on the value of the &quot;method-signature&quot; attribute.<br>.....&quot;<br><br>My first interpretation of this javadoc was that &quot;targets&quot; only has sense for &quot;action&quot;,<br>&quot;actionListener&quot;, &quot;validator&quot; and &quot;valueChangeListener&quot;. But note if that&#39;s true,<br>
someone could expect something like the description on retargetAttachedObjects, right?<br><br>The current behavior (Mojarra 2.0.3 and Myfaces 2.0.2) is the same, if we have two<br>nested composite components, that will throw a ClassCastException. There is a issue already<br>
open for this one:<br><br><a href="https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=755">https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=755</a><br><br>There are two possible alternatives here:<br>
<br> 1. Implement the algorithm proposed for retargetMethodExpressions and ignore <br>    composite:attribute &quot;targets&quot; property says. <br> 2. Implement the expected behavior of composite:attribute &quot;targets&quot; property and make<br>
    some changes to retargetMethodExpressions algorithm.<br><br>The intention is take option 2 and include it for JSF 2.0, because in theory should be <br>handled as an implementation detail of the algorithm (anyway it could be good to update <br>
the documentation with the same advice used for retargetAttachedObjects).<br><br>For &quot;action&quot;, &quot;actionListener&quot;, &quot;validator&quot; and &quot;valueChangeListener&quot; it is clear that<br>the action to take is something like this: <br>
<br> - If target is a composite component and that one &quot;retarget&quot; to other components and <br>   additionally does not implements [ActionSource2/EditableValueHolder], call:<br>   <br>   targetComponent.getAttributes().put(attributeName, attributeNameValueExpression);<br>
   <br>   and call retargetMethodExpressions recursively. Take care of apply the method twice<br>   and if the property pointed by &quot;attributeName&quot; was already set, revert its effects. <br>   <br>The tricky part is how to handle generic method expression properties. The javadoc says:<br>
<br>&quot;....<br>    # Otherwise, assume that the MethodExpression should be placed in the <br>      components attribute set. The runtme must create the MethodExpression <br>      instance based on the value of the &quot;method-signature&quot; attribute.<br>
.....&quot;<br><br>But I have identified three valid cases:<br><br> 1. testSimpleAttributeMethodExpressionEmpty.xhtml (Using an EL #{cc} reference)<br><br>    &lt;testComposite:simpleAttributeMethodExpressionEmpty id=&quot;cc1&quot; <br>
    customMethod=&quot;#{methodExpressionBean.doSomethingFunny}&quot;&gt;<br>    &lt;/testComposite:simpleAttributeMethodExpressionEmpty&gt;<br><br>    simpleAttributeMethodExpressionEmpty.xhtml<br><br>    &lt;composite:interface&gt;<br>
        &lt;composite:attribute <br>        name=&quot;customMethod&quot; <br>        method-signature=&quot;String doSomething(String)&quot;/&gt;<br>    &lt;/composite:interface&gt;<br>    &lt;composite:implementation&gt;<br>
        &lt;tc:testComponent id=&quot;testComponent&quot; customMethod=&quot;#{cc.attrs.customMethod}&quot;/&gt;<br>    &lt;/composite:implementation&gt;<br><br> 2. testSimpleAttributeMethodExpressionTarget.xhtml (Using &quot;targets&quot; to call <br>
    a property setter directly)<br><br>    &lt;testComposite:simpleAttributeMethodExpressionTarget id=&quot;cc1&quot;<br>     customMethod=&quot;#{methodExpressionBean.doSomethingFunny}&quot;&gt;<br>    &lt;/testComposite:simpleAttributeMethodExpressionTarget&gt;<br>
    <br>   simpleAttributeMethodExpressionTarget.xhtml<br>   <br>   &lt;composite:interface&gt;<br>        &lt;composite:attribute <br>        name=&quot;customMethod&quot; <br>        method-signature=&quot;String doSomething(String)&quot; <br>
        targets=&quot;testComponent&quot;/&gt;<br>   &lt;/composite:interface&gt;<br>    &lt;composite:implementation&gt;<br>        &lt;tc:testComponent id=&quot;testComponent&quot;/&gt;<br>    &lt;/composite:implementation&gt;<br>
    <br> 3. testCompositeAttributeMethodExpressionTarget.xhtml (Using &quot;targets&quot;, <br>    but the target component is a composite one)<br><br>    &lt;testComposite:compositeAttributeMethodExpressionTarget id=&quot;cc1&quot; <br>
    customMethod=&quot;#{methodExpressionBean.doSomethingFunny}&quot;&gt;<br>    &lt;/testComposite:compositeAttributeMethodExpressionTarget&gt;<br><br>    compositeAttributeMethodExpressionTarget.xhtml<br><br>    &lt;composite:interface&gt;<br>
        &lt;composite:attribute <br>        name=&quot;customMethod&quot; <br>        method-signature=&quot;String doSomething(String)&quot; <br>        targets=&quot;simpleAttributeMethodExpressionTarget&quot;/&gt;<br>    &lt;/composite:interface&gt;<br>
    &lt;composite:implementation&gt;<br>        &lt;testComposite:simpleAttributeMethodExpressionTarget <br>        id=&quot;simpleAttributeMethodExpressionTarget&quot;/&gt;<br>    &lt;/composite:implementation&gt;<br>    <br>
    simpleAttributeMethodExpressionTarget.xhtml (could be like in 1 or 2)<br><br>The case (1) actually works but the case (2) and (3) does not work on both <br>MyFaces 2.0.2 and Mojarra 2.0.3 . <br><br>I have created an issue on MyFaces here:<br>
<br><a href="https://issues.apache.org/jira/browse/MYFACES-2946">https://issues.apache.org/jira/browse/MYFACES-2946</a><br><br>a attached a working patch too if you want to take a look at it:<br><br><a href="https://issues.apache.org/jira/secure/attachment/12457512/MYFACES-2946-1.patch">https://issues.apache.org/jira/secure/attachment/12457512/MYFACES-2946-1.patch</a><br>
 <br>Suggestions are welcome<br><br>regards,<br><br>Leonardo Uribe<br>