[jsr-314-open-mirror] [jsr-314-open] Fwd: PostAddToViewEvent publishing conditions

Andy Schwartz andy.schwartz at oracle.com
Wed May 26 12:49:48 EDT 2010


On 5/26/10 1:27 AM, Martin Marinschek wrote:
> Hi Andy,
>
> my 2cents (isn´t worth much in this discussion if I don´t look any
> deeper into this ;)
>
>   
>> Given that ui:decorate is a non-trimming ui:composition, why would these
>> behave differently with respect to interaction with the TemplateClient?  I
>> would think that both of these handlers should be calling pushClient().
>>     
>
> I don´t see why ui:decorate should be different from ui:composition, either.
>   

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()).


>> Also, the multi-level search strategy seems somewhat questionable to me.  A
>> template exposes a certain number of of names into which content could be
>> inserted.  The consumer of the template leverages that contract and
>> specifies content to be inserted into some subset of those names.  When
>> attempting to locate content to insert, why should the template look any
>> further up the stack than the nearest consumer (ie. the most recently pushed
>> TemplateClient)?
>>     
>
>
> Well, templates are certainly hierarchical - does the nearest consumer
> carry all information, or just the one which is defined in itself?
>   

My take on this is that templates are reusable objects with a specific 
contract (much like composite components, or, well, any component for 
that matter).  The contract is that the template exposes certain slots 
that users of the template can fill in with their own content.  The 
names of the slots are defined via ui:insert tags in the template 
implementation.

Yeah, I know, you already know this. :-)

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.

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.


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

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.

To me this looks like an old implementation quirk that we have 
inherited.  Does someone here happen to understand why this is useful?  
If this is useful, we need to document this behavior.  If it isn't 
useful, we should remove this part of the implementation.

Andy

> best regards,
>
> Martin
>
>   




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