[jsr-314-open-mirror] [jsr-314-open] composite components: targets attribute revisited

Jakob Korherr jakob.korherr at gmail.com
Thu Oct 28 12:42:51 EDT 2010


Hi,

Currently there are a lot of discussions (on spec-issues, on this list
and also internally) about the problems with the targets attribute in
the composite component interface and I'd like to wrap these up here.

IMHO the targets attribute is something we should get rid of, because
it directly points to the implementation section and frankly somehow
feels like the following piece of code:

if (this instanceof Foo)
{
    // do something
}

The interface section should just specify the interface for the
composite component and should not include any information about the
implementation section. However, the implementation section should of
course refer to the interface section. Unfortunately the targets
attribute works against this. And furthermore the targets attribute
also confuses users, because the don't really know which clientid to
use (especially with nested components in the implementation section).

The first step needed here is to put all attributes (also the
"well-known" ones like action, actionListener, valueChangeListener) on
the composite component attribute map in order to access them via
#{cc.attrs.attributeName}. In this way the user can refer from the
implementation section to the related attribute in the interface
section, regardless of what it does. This was already discussed and is
also already accepted, I guess.

The next step is to remove the targets attribute from cc:actionSource,
cc:editableValueHolder and cc:valueHolder. Here we have two options:

1) add new composite tags that insert the related listeners in the
implementation section (proposed by Leonardo):

     <ez:loginPanel id="loginPanel" model="#{bean}">
        <f:actionListener for="loginEvent"
                          binding="#{bean.loginEventListener}" />
        <f:actionListener for="cancelEvent"
                          binding="#{bean.cancelEventListener}" />
      </ez:loginPanel>

      <composite:interface name="loginPanel">
        <composite:actionSource name="loginEvent" />
        <composite:actionSource name="cancelEvent" />
      </composite:interface>
      <composite:implementation>
                  <h:commandButton name="button1">
                         <composite:insertActionSource name="loginEvent"/>
                  </h:commandButton>
                  <x:mycompositecomponent name="button2">
                         <composite:insertActionSource
name="cancelEvent" for="someOtherEvent"/>
                  </x:mycompositecomponent>
      </composite:implementation>


2) use the existing tags like f:actionListener and
f:valueChangeListener and provide the actionSource,.. via
ValueExpression:

<ez:loginPanel id="loginPanel" model="#{bean}">
        <f:actionListener for="loginEvent"
                          binding="#{bean.loginEventListener}" />
        <f:actionListener for="cancelEvent"
                          binding="#{bean.cancelEventListener}" />
      </ez:loginPanel>

      <composite:interface name="loginPanel">
        <composite:actionSource name="loginEvent" />
        <composite:actionSource name="cancelEvent" />
      </composite:interface>
      <composite:implementation>
                  <h:commandButton name="button1">
                         <f:actionListener
binding="#{cc.actionSource.loginEvent}"/>
                  </h:commandButton>
                  <x:mycompositecomponent name="button2">
                         <f:actionListener
binding="#{cc.actionSource.cancelEvent}" for="someOtherEvent"/>
                  </x:mycompositecomponent>
      </composite:implementation>


Frankly I'd prefer option 2, because it is very similar to how we
handle cc:attribute --> #{cc.attrs.xxx}.


One remaining problem here, however, is how to handle non-required
method-attributes (there's a thread about this on the
myfaces-user-list). IMO the default attribute of cc:attribute should
be able to resolve to a MethodExpression and not only to a String (I
think this is already a spec-issue), but it should also work without
providing a default value. In that case #{cc.attrs.thatAttribute}
should internally return an empty action/listener/... so that there
are no problems with the related implementation-components which refer
to this attribute.

What do you think?

Regards,
Jakob

-- 
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