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

Leonardo Uribe lu4242 at gmail.com
Thu Oct 28 16:09:57 EDT 2010


Hi

2010/10/28 Ganesh <ganesh at j4fry.org>

> Leo, IMO your example wouldn't need to fail: the nested actionListener with
> binding="#{cc.actionSource.loginEvent}" would need to execute *all*
> actionListeners that have been bound to "loginEvent". In this case
> "#{bean.loginEventListener}" and "#{bean.loginEventListener2}" would reside
> in a Map named cc.actionSource.loginEvent and could both be executed.
> Wouldn't this work?
>
>
Yes, it could work in this specific case (cc:actionSource), but things get
complex when you consider other behavioral interfaces like ValueHolder,
EditableValueHolder and ClientBehaviorHolder.


> IMO Jakob's approach #2 would work, is easy to understand and logical
> within the entire context. I think acceptance will be better than targets,
> methodTarget or methodType constructs, because this is what I tried first
> before realizing how this entire thing was set up and I saw other developers
> getting into JSF 2 and running exactly the way #2 Jakob proposed.
>
>
Ok, maybe here there is a confusion. There are two different problems
(really there are not problems, instead, there are opportunities to make
composite component syntax even better).

a. Replace cc:attribute "targets" with EL expressions.This was already
solved (finally was committed a new attribute "targetAttributeName").

b. Replace
cc:actionSource/cc:valueHolder/cc:editableValueHolder/cc:clientBehavior
"targets" with something else.

The proposal required is for b.

Let's see the relationship between the tags if Jakob's approach is taken:

cc:actionSource  -----------------> f:actionListener

cc:valueHolder    -----------------> f:converter (and every one that expose
Converter)

cc:editableValueHolder --------> f:valueChangeListener, f:validator (and
every one that expose Validator)

cc:clientBehavior -----------------> ?????? this is an special case, so
users can define whatever that expose ClientBehavior.

In theory, the approach #2 only works for cc:actionSource but nobody else.
In the other cases it just too limited to handle all posible cases.

Suggestions are welcome

best regards,

Leonardo Uribe


> Best regards,
> Ganesh
>
> Am 28.10.2010 19:56, schrieb Leonardo Uribe:
>
>> Hi
>>
>> To be more explicit, this is the example that should fail:
>>
>> <ez:loginPanel id="loginPanel" model="#{bean}">
>> <f:actionListener for="loginEvent"
>>                          binding="#{bean.loginEventListener}" />
>> <f:actionListener for="loginEvent"
>>                          binding="#{bean.loginEventListener2}" />
>> <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>
>>
>> In this case, the binding #{cc.actionSource.loginEvent} does not point to
>> just
>> one actionListener.
>>
>> regards,
>>
>> Leonardo
>>
>>
>> 2010/10/28 Jakob Korherr <jakob.korherr at gmail.com <mailto:
>> jakob.korherr at gmail.com>>
>>
>>
>>    Hi,
>>
>>    In option 2 the f:actionListener is just used as a reference to the
>>    cc:actionSource (just as in option 1 but without introducing a new
>>    composite-tag).
>>
>>    Thus it would actually be possible to have multiple ones!
>>
>>    Regards,
>>    Jakob
>>
>>    2010/10/28 Leonardo Uribe <lu4242 at gmail.com <mailto:lu4242 at gmail.com
>> >>:
>>     > Hi
>>     >
>>     > 2010/10/28 Jakob Korherr <jakob.korherr at gmail.com <mailto:
>> jakob.korherr at gmail.com>>
>>
>>     >>
>>     >> 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?
>>     >>
>>     >
>>     > Well, unfortunately use option 2 forces to use just one
>> f:actionListener per
>>     > actionSource, and in theory, it should be possible to have multiple
>> ones.
>>     >
>>     > best regards,
>>     >
>>     > Leonardo Uribe
>>     >
>>     >>
>>     >> Regards,
>>     >> Jakob
>>     >>
>>     >> --
>>     >> Jakob Korherr
>>     >>
>>     >> blog: http://www.jakobk.com
>>     >> twitter: http://twitter.com/jakobkorherr
>>     >> work: http://www.irian.at
>>     >
>>     >
>>
>>
>>
>>    --
>>    Jakob Korherr
>>
>>    blog: http://www.jakobk.com
>>    twitter: http://twitter.com/jakobkorherr
>>    work: http://www.irian.at
>>
>>
>>
> --
> "There are two kinds of people in the world, those who believe there are
> two kinds of people and those who don't."
> — Robert Benchley
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/jsr-314-open-mirror/attachments/20101028/6b77de5d/attachment-0002.html 


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