My comments on Andy's mail, now officially to the list.
=========================================
Hi Andy,
ok, I will answer here, and will also try to forward when I see your
mail on the list ;)
Actually meant to say that I believe that DecorateHandler got this
one
right. (Calling pushClient() is the way to go.)
ok
Unless someone understands why the implementation is inconsistent
across
these two cases, I think that we should align the implementations. Note
that given the bug that Max logged (against Mojarra):
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1684
I believe that CompositionHandler has got this one right (ie. both
DecorateHandler and CompositionHandler should be calling pushClient()).
ok
If the template itself happens to depend on yet another template, I
view
that as an implementation detail of the template. So, if we've got this
situation:
- view.xhtml, which includes:
- outerTemplate.xhtml, which includes:
- innerTemplate.xhtml
In my ideal world (which, at the moment, does not match reality), view.xhtml
should only be aware of the slots that are exposed by outerTemplate.xhtml.
That is, view.xhtml should not depend on the fact that outerTemplate.xhtml
happens to include innerTemplate.xhtml, which may have its own slots.
The reality is that when nesting templates, the outermost template exposes
*all* of the slots defined by any nested templates (no matter how many
levels deep) to the consumer. This seems like a violation of encapsulation
to me. We are exposing implementation details up through the template
hierarchy that, I think, should not necessarily be exposed.
Of course, I understand that it may be useful to be able to pass content
from view.xhtml all the way through to a slot defined by
innerTemplate.xhtml. If outerTemplate.xhtml wants to allow certain content
to be passed through from view.xhtml to innerTemplate.xthml, that's fine.
However, this should be done by introducing a ui:insert inside of
outerTemplate.xhtml - ie. by explicitly exposing a new slot that consumers
of outerTemplate.xhtml can rely on. That way, if the author of
outerTemplate.xhtml reconsiders the implementation and decides not to
delegate to innerTemplate.xhtml after all, users of outerTemplate.xhtml are
not hosed.
I totally understand your notion - and I agree. However, this is not
how Facelets works now. For me, this is a little bit like a method
call where suddenly inner method calls inherit the parameters from the
outside. FWIW, also the facelets parameters for composite components
(old style) were inherited this way, at least for a long time (I am
not sure if this has been fixed at some point of time). I find this
ugly.
Oh well, this looks like another cases where I am many years too
late. That
seems to be my fate these days.
Even if we cannot change this behavior for ui:insert now, I do think it is
important that we avoid this behavior for composite components. Since we
are tinkering with the composite:inertFacet/composite:insertChildren
implementations now to be more Facelets/TemplateClient-like, let's just be
careful to avoid introducing the Facelets nested insert behavior into
composite components.
agreed
>> Right, so I see that InsertHandler is implemented this way,
but... why?
>> Seems silly to have ui:insert serve two entirely different purposes -
>> ie.
>> to both identify an insertion point as well as to define content for
>> included templates. Why should ui:insert act both as a ui:insert *and*
>> as
>> a ui:define? If a template author wants to pass content through from an
>> outer page to an inner/nested template, seems like the right way to
>> accomplish this would be to wrap the ui:insert inside of a ui:define.
>>
>
> Well, if you define a template, you use ui:insert to mark the spots
> where content can be - and then you include default content right
> away. Is it this which makes ui:insert a thing of both worlds?
>
Let's take a step back and look at the role of the TemplateClient contract.
TemplateClient allows consumers of templates (eg. ui:composition) to
provide access to content that should be inserted into the template - ie.
content defined by ui:define, inserted into ui:insert. So, for example,
both CompositionHandler and DecorateHandler are TemplateClients.
ui:insert is clearly a user of the TemplateClient interface. InsertHandler
(via a call to FaceletContext.includeDefinition()) pulls in content provided
by outer TemplateClients (eg. an ancestor ui:composition).
This is all well and good.
Where things get strange is that InsertHandler also implements
TemplateClient. This means that, in addition to being a consumer of
TemplateClient content, ui:insert also exposes its own content for
consumption by other consumers of TemplateClients.
So, if you've got:
<ui:insert name="foo">
body content
</ui:insert>
The "body content" serves two roles:
1. It provides default content in the event that no matching ui:define for
"foo" can be found.
2. It is exposed as content for consumption while performing the definition
inclusion (during the call to FaceletContext.includeDefinition()).
Case #1 is expected/documented.
that is the case I meant - wasn´t sure if the existing implementation
tried to reach there.
Case #2 is where ui:insert seems to acting as a ui:define. This is
non-obvious, and, as far as I can tell, not documented.
brrr, ugly. Has to go.
best regards,
Martin
--
http://www.irian.at
Your JSF powerhouse -
JSF Consulting, Development and
Courses in English and German
Professional Support for Apache MyFaces
--
http://www.irian.at
Your JSF powerhouse -
JSF Consulting, Development and
Courses in English and German
Professional Support for Apache MyFaces