[jsr-314-open-mirror] [jsr-314-open] composite:attribute "targets" property does not match with ViewDeclarationLanguage.retargetMethodExpressions

Jakob Korherr jakob.korherr at gmail.com
Fri Oct 22 04:42:13 EDT 2010


Hi,

I think we should do this a little differently:

1) try to add the e.g. ActionListener to the component specified in
the targets attribute, if possible. If it is not possible, log a
warning.

2) also expose the "well-known" attributes ("action",
"actionListener", ...) on the composite component attribute map, this
means being able to access the action attribute via #{cc.attrs.action}
(currently not possible, because those attributes are not put on the
attribute map).

Thus the user can use the targets attribute if he/she wants to (and of
course, if it is possible) and also use #{cc.attrs.action} to refer to
the action attribute (like to any other attribute).

Frankly I really don't understand why this was separated in the first
place. Of course, the targets attribute is neat, but IMHO it is also
kinda confusing. I find it a lot easier to access _every_ attribute
(regardless if well-known or custom) via #{cc.attrs.attributeName}.
Furthermore using this approach you can support nesting normal
components and also nesting composite components.

In addition the targets attribute can't solve a scenario in which the
action attribute of the inner component is required (most likely the
attribute from a composite component), because you need to enter a
value for the attribute, but you currently can't use
#{cc.attrs.action}, because this one points "nowhere".

Regards,
Jakob

2010/10/19 Leonardo Uribe <lu4242 at gmail.com>:
> Hi
>
> 2010/10/19 Ed Burns <edward.burns at oracle.com>
>>
>> >>>>> On Mon, 18 Oct 2010 20:36:06 -0500, Leonardo Uribe
>> >>>>> <lu4242 at gmail.com> said:
>>
>> [...]
>>
>> LU> There are two possible alternatives here:
>>
>> LU>  1. Implement the algorithm proposed for retargetMethodExpressions
>> LU> and ignore composite:attribute "targets" property says.
>>
>> LU>  2. Implement the expected behavior of composite:attribute "targets"
>> LU> property and make some changes to retargetMethodExpressions
>> LU> algorithm.
>>
>> LU> The intention is take option 2 and include it for JSF 2.0, because
>> LU> in theory should be handled as an implementation detail of the
>> LU> algorithm (anyway it could be good to update the documentation with
>> LU> the same advice used for retargetAttachedObjects).
>>
>> Certainly you have identified a valid issue.  The root problem is that
>> the top level component needs to have a Java programming way to expose
>> its composite-ness.
>>
>> LU> For "action", "actionListener", "validator" and
>> LU> "valueChangeListener" it is clear that the action to take is
>> LU> something like this:
>>
>> LU>  - If target is a composite component and that one "retarget" to
>> LU> other components and additionally does not implements
>> LU> [ActionSource2/EditableValueHolder], call:
>>
>> LU>    targetComponent.getAttributes().put(attributeName,
>> LU> attributeNameValueExpression);
>>
>> LU>    and call retargetMethodExpressions recursively. Take care of
>> LU> apply the method twice and if the property pointed by
>> LU> "attributeName" was already set, revert its effects.
>>
>> The solution you propose will work, but it feels a bit too
>> implementation-ish.  Right now we declare that every compositeComponent
>> must be a NamingContainer.  Perhaps it's time to define a new abstract
>> sub-class of NamingContainer that is a union of all the behavioral
>> interfaces?
>>
>> public abstract class javax.faces.component.CompositeComponent
>> implements NamingContainer, ActionSource2, EditableValueHolder {
>>  public abstract void acceptRetargetedMethodExpressions(BeanInfo
>>    ccMetadata);
>> }
>>
>
> I like the way it works now. For example, tomahawk t:inputHtml component was
> rewritten into a composite component, and it is a good example about when it
> could
> be useful that the only requerimiento for a component to be composite is
> implement
> NamingContainer:
>
> <composite:interface componentType="org.apache.myfaces.InputHtml">
>
> public class InputHtml extends HtmlInputText implements NamingContainer,
> UniqueIdVendor {
>
> In my understanding, if a composite component base class implements a
> behavioral interface,
> (ActionSource2, EditableValueHolder, ...), "targets" behavior must not be
> allowed, because
> the code handling that will be on the base class. In the example shown
> InputHtml extends
> from HtmlInputText, so it implements EditableValueHolder.
>
> To decide when "targets" behavior applies I have something like this:
>
> if (isCompositeComponentRetarget(context, innerComponent, attributeName) &&
> !(innerComponent instanceof ActionSource2))
> {
>    //cc retarget
> }
> else
> {
>   //process on innerComponent
> }
>
> isCompositeComponentRetarget do two things:
>
> - Check if the component is a composite one.
> - Check if the attribute was defined looking on the BeanInfo.
>
> Leonardo
>
>> LU> The tricky part is how to handle generic method expression
>> LU> properties. The javadoc says:
>>
>> We could specify whatever we needed in that
>> acceptRetargetedMethodExpressions() method.
>>
>> Ed
>>
>> --
>> | edward.burns at oracle.com | office: +1 407 458 0017
>> | homepage:               | http://ridingthecrest.com/
>> | 16 work days until German Oracle User's Group Conference
>
>



-- 
Jakob Korherr

blog: http://www.jakobk.com
twitter: http://twitter.com/jakobkorherr
work: http://www.irian.at



More information about the jsr-314-open-mirror mailing list