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(a)gmail.com>:
Hi
2010/10/19 Ed Burns <edward.burns(a)oracle.com>
>
> >>>>> On Mon, 18 Oct 2010 20:36:06 -0500, Leonardo Uribe
> >>>>> <lu4242(a)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(a)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