You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by "Leonardo Uribe (JIRA)" <de...@myfaces.apache.org> on 2010/10/19 03:32:28 UTC

[jira] Updated: (MYFACES-2946) composite:attribute "targets" property does not match with ViewDeclarationLanguage.retargetMethodExpressions

     [ https://issues.apache.org/jira/browse/MYFACES-2946?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Leonardo Uribe updated MYFACES-2946:
------------------------------------

    Status: Patch Available  (was: Open)

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

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.